Juni 2019

Band 34, Nummer 6

[Speech]

Text-zu-Sprache-Synthese in .NET

Von Ilia Smirnov | Juni 2019

Ich fliegen häufig nach Finnland, um meine Mutter zu besuchen. Jedes Mal, wenn das Flugzeug auf dem Flughafen in Vantaa landet, bin ich überrascht, wie wenig Passagiere zum Flughafenausgang gehen. Die überwiegende Mehrheit macht sich auf den Weg zu Anschlussflügen zu Zielen in ganz Mittel- und Osteuropa. Wenn das Flugzeug mit seinem Landeanflug beginnt, ist es daher kein Wunder, dass es eine Flut von Ankündigungen über Anschlussflüge gibt. „Wenn Ihr Ziel Tallinn ist, suchen Sie nach Gate 123“, „Für den Flug XYZ nach Sankt Petersburg begeben Sie sich zu Gate 234“ und so weiter. Natürlich sprechen die Flugbegleiter in der Regel nicht ein Dutzend Sprachen, also verwenden sie Englisch, was nicht die Muttersprache der meisten Passagiere ist. Wie können Informationen angesichts der Qualität der Durchsagesysteme (PA-Systeme) in Flugzeugen effektiv vermittelt werden, wenn dazu noch Triebwerksgeräusche, weinende Babys und andere Störungen kommen?

Nun, jeder Sitzplatz ist mit Kopfhörern ausgestattet. Viele (wenn nicht sogar alle) Langstreckenflugzeuge verfügen heute über individuelle Bildschirme (und lokale Flugzeuge bieten mindestens unterschiedliche Audiokanäle an). Was wäre, wenn ein Passagier die Sprache für Durchsagen wählen könnte und ein Bordcomputersystem es den Flugbegleitern ermöglichte, dynamische (d.h. nicht vorab aufgezeichnete) Sprachnachrichten zu erstellen und zu senden? Die größte Herausforderung dabei ist die dynamische Natur der Durchsagen. Es ist einfach, Sicherheitshinweise, Verpflegungsoptionen usw. vorab aufzuzeichnen, da sie nur selten aktualisiert werden. Aber wir müssen Botschaften auch spontan erstellen können.

Glücklicherweise gibt es eine ausgereifte Technologie, die helfen kann: die Text-zu-Sprache-Synthese (Text-to-Speech, TTS). Wir bemerken solche Systeme selten, aber sie sind allgegenwärtig: öffentliche Durchsagen, Ansagen in Call Centern, Navigationsgeräten, Spielen, Smart Devices und anderen Anwendungen sind Beispiele, bei denen vorab aufgezeichnete Ansagen nicht ausreichen oder die Verwendung eines digitalisierten Signals aus Speichergründen verboten ist (der Speicherbedarf eines von einer TTS-Engine gelesenes Texts ist viel kleiner als der einer digitalisierten Waveform).

Computergestützte Sprachsynthese ist nicht wirklich neu. Telekommunikationsunternehmen haben in TTS investiert, um die Grenzen der vorab aufgezeichneten Nachrichten zu überwinden, und militärische Forscher haben mit Sprachansagen und -warnungen experimentiert, um komplexe Steuerungsoberflächen zu vereinfachen. Ebenso wurden tragbare Synthesizer für Menschen mit Beeinträchtigungen entwickelt. Um eine Vorstellung davon zu bekommen, wozu solche Geräte vor 25 Jahren fähig waren, hören Sie sich den Track „Keep Talking“ auf dem 1994 erschienenen Pink Floyd-Album „The Division Bell“ an, auf dem Stephen Hawking seinen berühmten Satz sagt: „All we need to do is to make sure we keep talking“ (Wir müssen nur sicherstellen, dass wir weiterhin miteinander reden).

TTS-APIs werden oft zusammen mit ihrem „Gegenstück“ – der Spracherkennung – bereitgestellt. Während Sie beides für eine effektive Interaktion zwischen Mensch und Computer benötigen, konzentriert sich dieser Artikel speziell auf die Sprachsynthese. Ich werde die Microsoft .NET TTS-API verwenden, um einen Prototyp eines Durchsagesystems für Flugzeuge zu erstellen. Ich werde auch hinter die Kulissen schauen, um die Grundlagen des „Unit Selection“-Ansatzes für TTS zu verstehen. Auch wenn ich die Erstellung einer Desktopanwendung zeige, gelten die hier genannten Prinzipien direkt für cloudbasierte Lösungen.

Erstellen eines eigenen Sprachsystems

Bevor wir den Prototyp des Borddurchsagesystems erstellen, lassen Sie uns die API mit einem einfachen Programm untersuchen. Starten Sie Visual Studio, und erstellen Sie eine Konsolenanwendung. Fügen Sie einen Verweis auf System.Speech hinzu, und implementieren Sie die Methode in Abbildung1.

Abbildung 1: System.Speech.Synthesis-Methode

using System.Speech.Synthesis;
namespace KeepTalking
{
  class Program
  {
    static void Main(string[] args)
    {
      var synthesizer = new SpeechSynthesizer();
      synthesizer.SetOutputToDefaultAudioDevice();
      synthesizer.Speak("All we need to do is to make sure we keep talking");
    }
  }
}

Kompilieren Sie die Anwendung, und führen Sie sie aus. Mit nur wenigen Codezeilen haben Sie den berühmten Satz von Hawking repliziert.

Bei der Eingabe dieses Codes hat IntelliSense ein Fenster mit allen öffentlichen Methoden und Eigenschaften der SpeechSynthesizer-Klasse geöffnet. Wenn Ihnen das entgangen sein sollte, verwenden Sie die Tastenkombination STRG+LEERTASTE oder den PUNKT (oder sehen Sie sich bit.ly/2PCWpat an). Was ist hier interessant?

Zunächst können Sie verschiedene Ausgabeziele festlegen. Das Ziel kann eine Audiodatei oder ein Stream oder sogar NULL sein. Zweitens sehen Sie sowohl synchrone (wie im vorherigen Beispiel) als auch asynchrone Ausgaben. Sie können auch die Lautstärke und die Sprechgeschwindigkeit anpassen, die Ausgabe anhalten und fortsetzen sowie Ereignisse empfangen. Außerdem können Sie Stimmen auswählen. Dieses Feature ist hier wichtig, da Sie es verwenden, um Ausgaben in verschiedenen Sprachen zu generieren. Aber welche Stimmen sind verfügbar? Das finden wir heraus, indem wir den Code in Abbildung 2 verwenden.

Abbildung 2: Code für Sprachinformationen

using System;
using System.Speech.Synthesis;
namespace KeepTalking
{
  class Program
  {
    static void Main(string[] args)
    {
      var synthesizer = new SpeechSynthesizer();
      foreach (var voice in synthesizer.GetInstalledVoices())
      {
        var info = voice.VoiceInfo;
        Console.WriteLine($"Id: {info.Id} | Name: {info.Name} |
          Age: {info.Age} | Gender: {info.Gender} | Culture: {info.Culture}");
      }
      Console.ReadKey();
    }
  }
}

Auf meinem Computer mit Windows 10 Home ist dies die sich ergebende Ausgabe aus Abbildung 2:

Id: TTS_MS_EN-US_DAVID_11.0 | Name: Microsoft David Desktop |
  Age: Adult | Gender: Male | Culture: en-US
Id: TTS_MS_EN-US_ZIRA_11.0 | Name: Microsoft Zira Desktop |
  Age: Adult | Gender: Female | Culture: en-US

Es gibt nur zwei englische Stimmen, und wie sieht es mit anderen Sprachen aus? Nun, jede Stimme benötigt etwas Speicherplatz, sodass sie standardmäßig nicht installiert werden. Um sie hinzuzufügen, navigieren Sie zu „Start > Einstellungen > Zeit und Sprache > Region und Sprache“, und klicken Sie auf „Sprache hinzufügen“. Stellen Sie dabei sicher, dass Sie „Speech“ in den optionale Funktionen auswählen. Auch wenn Windows mehr als 100 Sprachen unterstützt, unterstützt TTS nur etwa 50 Sprachen. Sie finden die Liste der unterstützten Sprachen unter bit.ly/2UNNvba.

Nach dem Neustart Ihres Computers sollte ein neues Language Pack verfügbar sein. Nachdem ich in meinem Fall Russisch hinzugefügt habe, wurde eine neue Stimme installiert:

Id: TTS_MS_RU-RU_IRINA_11.0 | Name: Microsoft Irina Desktop |
  Age: Adult | Gender: Female | Culture: ru-RU

Nun können Sie zum ersten Programm zurückkehren und diese beiden Zeilen anstelle des synthesizer.Speak-Aufrufs hinzufügen:

synthesizer.SelectVoice("Microsoft Irina Desktop");
synthesizer.Speak("Всё, что нам нужно сделать, это продолжать говорить");

Wenn Sie zwischen den Sprachen wechseln möchten, können Sie hier und da SelectVoice-Aufrufe einfügen. Aber eine bessere Möglichkeit besteht darin, Speech eine Struktur hinzuzufügen. Dazu verwenden wir die PromptBuilder-Klasse, wie in Abbildung 3 gezeigt.

Abbildung 3: Die PromptBuilder-Klasse

using System.Globalization;
using System.Speech.Synthesis;
namespace KeepTalking
{
  class Program
  {
    static void Main(string[] args)
    {
      var synthesizer = new SpeechSynthesizer();
      synthesizer.SetOutputToDefaultAudioDevice();
      var builder = new PromptBuilder();
      builder.StartVoice(new CultureInfo("en-US"));
      builder.AppendText("All we need to do is to keep talking.");
      builder.EndVoice();
      builder.StartVoice(new CultureInfo("ru-RU"));
      builder.AppendText("Всё, что нам нужно сделать, это продолжать говорить");
      builder.EndVoice();
      synthesizer.Speak(builder);
    }
  }
}

Beachten Sie, dass Sie EndVoice aufrufen müssen, ansonsten erhalten Sie einen Laufzeitfehler. Darüber hinaus habe ich CultureInfo als eine andere Möglichkeit verwendet, eine Sprache anzugeben. PromptBuilder verfügt über viele nützliche Methoden, aber ich möchte Ihre Aufmerksamkeit auf AppendTextWithHint lenken. Probieren Sie diesen Code aus:

var builder = new PromptBuilder();
builder.AppendTextWithHint("3rd", SayAs.NumberOrdinal);
builder.AppendBreak();
builder.AppendTextWithHint("3rd", SayAs.NumberCardinal);
synthesizer.Speak(builder);

Eine weitere Möglichkeit, die Eingabe zu strukturieren und anzugeben, wie sie zu lesen ist, ist die Verwendung von SSML (Speech Synthesis Markup Language), einer plattformübergreifenden Empfehlung, die von der internationalen Voice Browser Working Group (w3.org/TR/speech-synthesis) entwickelt wurde. Microsoft TTS-Engines bieten umfassende Unterstützung für SSML. So erfolgt die Verwendung:

string phrase = @"<speak version=""1.0""
  xmlns=""http://www.w3.org/2001/10/synthesis""
  xml:lang=""en-US"">";
phrase += @"<say-as interpret-as=""ordinal"">3rd</say-as>";
phrase += @"<break time=""1s""/>";
phrase += @"<say-as interpret-as=""cardinal"">3rd</say-as>";
phrase += @"</speak>";
synthesizer.SpeakSsml(phrase);

Beachten Sie, dass ein anderer Aufruf der SpeechSynthesizer-Klasse genutzt wird.

Jetzt sind Sie bereit, am Prototyp zu arbeiten. Erstellen Sie dieses Mal ein neues WPF-Projekt (Windows Presentation Foundation). Fügen Sie ein Formular und eine Reihe von Schaltflächen für Ansagen in zwei verschiedenen Sprachen hinzu. Fügen Sie dann Klickhandler hinzu, wie im XAML in Abbildung 4 gezeigt.

Abbildung 4: Der XAML-Code

using System.Collections.Generic;
using System.Globalization;
using System.Speech.Synthesis;
using System.Windows;
namespace GuiTTS
{
  public partial class MainWindow : Window
  {
    private const string en = "en-US";
    private const string ru = "ru-RU";
    private readonly IDictionary<string, string> _messagesByCulture =
      new Dictionary<string, string>();
    public MainWindow()
    {
      InitializeComponent();
      PopulateMessages();
    }
    private void PromptInEnglish(object sender, RoutedEventArgs e)
    {
      DoPrompt(en);
    }
    private void PromptInRussian(object sender, RoutedEventArgs e)
    {
      DoPrompt(ru);
    }
    private void DoPrompt(string culture)
    {
      var synthesizer = new SpeechSynthesizer();
      synthesizer.SetOutputToDefaultAudioDevice();
      var builder = new PromptBuilder();
      builder.StartVoice(new CultureInfo(culture));
      builder.AppendText(_messagesByCulture[culture]);
      builder.EndVoice();
      synthesizer.Speak(builder);
    }
    private void PopulateMessages()
    {
      _messagesByCulture[en] = "For the connection flight 123 to
        Saint Petersburg, please, proceed to gate A1";
      _messagesByCulture[ru] =
        "Для пересадки на рейс 123 в  Санкт-Петербург, пожалуйста, пройдите к выходу A1";
    }
  }
}

Offensichtlich ist dies nur ein sehr kleiner Prototyp. In der Praxis wird PopulateMessages wahrscheinlich aus einer externen Ressource lesen. Beispielsweise kann ein Flugbegleiter eine Datei mit Nachrichten in mehreren Sprachen generieren, indem er eine Anwendung verwendet, die einen Dienst wie Bing Translator (bing.com/translator) aufruft. Das Formular wird viel komplexer sein und dynamisch auf der Grundlage der verfügbaren Sprachen generiert. Es wird Fehlerbehandlung verfügbar sein und so weiter. Hier geht es aber darum, die Kernfunktionalität zu veranschaulichen.

Dekonstruieren von Sprache

Bisher haben wir unser Ziel mit einer erstaunlich kleinen Codebasis erreicht. Lassen Sie uns die Gelegenheit nutzen, hinter die Kulissen zu schauen und besser zu verstehen, wie TTS-Engines funktionieren.

Es gibt viele Ansätze für die Erstellung eines TTS-Systems. Historisch gesehen haben Forscher versucht, eine Reihe von Ausspracheregeln zu ermitteln, auf denen sie Algorithmen aufbauen können. Wenn Sie jemals eine Fremdsprache gelernt haben, sind Sie mit Regeln wie „Buchstabe c vor e, i, y wird als s wie in city ausgesprochen, aber vor a, o, u als k wie in cat“ vertraut. Leider gibt es so viele Ausnahmen und Sonderfälle wie Ausspracheveränderungen in aufeinanderfolgenden Wörtern, dass es schwierig ist, ein umfassendes Regelwerk zu erstellen. Darüber hinaus neigen die meisten dieser Systeme dazu, eine eigene „maschinelle“ Stimme zu produzieren: Stellen Sie sich einen Anfänger in einer Fremdsprache vor, der ein Wort Buchstabe für Buchstabe ausspricht.

Für natürlicher klingende Sprache hat sich die Forschung auf Systeme verlagert, die auf großen Datenbanken von aufgezeichneten Sprachfragmenten basieren, und diese Engines dominieren nun den Markt. Diese Engines, die allgemein als Concatenation Unit Selection TTS bekannt sind, selektieren Sprachproben (Units, Einheiten) basierend auf dem Eingabetext und verketten sie zu Sätzen. Engines verwenden in der Regel eine zweistufige Verarbeitung, die Compilern sehr ähnlich ist: Zunächst wird die Eingabe in eine interne listen- oder baumartige Struktur mit phonetischer Transkription und zusätzlichen Metadaten analysiert und anschließend die Sprachausgabe basierend auf dieser Struktur synthetisiert.

Da es sich um natürliche Sprachen handelt, sind die Parser komplexer als bei Programmiersprachen. Über die Tokenisierung hinaus (das Auffinden von Satz- und Wortgrenzen) müssen Parser Rechtschreibfehler korrigieren, Sprachteile identifizieren, Interpunktion analysieren und Abkürzungen, Zusammenziehungen und Sonderzeichen entschlüsseln. Die Parserausgabe wird in der Regel nach Phrasen oder Sätzen aufgeteilt und in Sammlungen zusammengefasst, die Wörter beschreiben, die Metadaten wie Wortart, Aussprache, Betonung und so weiter gruppieren und transportieren.

Parser sind verantwortlich für das Auflösen von Mehrdeutigkeiten in der Eingabe. Was ist z.B. „Dr.“? Ist es „Doktor“ wie in „Dr. Smith“ oder „Drive“ wie in „Privet Drive“? Und ist „Dr.“ ein Satz, weil er mit einem Großbuchstaben beginnt und mit einem Punkt endet? Ist „project“ ein Nomen oder ein Verb? Dies ist wichtig zu wissen, da die Betonung auf verschiedenen Silben liegt.

Diese Fragen sind nicht immer einfach zu beantworten, und viele TTS-Systeme haben separate Parser für bestimmte Bereiche: Zahlen, Daten, Abkürzungen, Akronyme, geografische Namen, spezielle Textformen wie URLs und so weiter. Sie sind außerdem sprach- und regionsspezifisch. Glücklicherweise werden solche Probleme schon seit langem untersucht, und wir haben gut entwickelte Frameworks und Bibliotheken, auf die wir uns stützen können.

Der nächste Schritt ist die Generierung von Ausspracheformen, z.B. das Kennzeichnen des Baums mit Klangsymbolen (z.B. die Transformation von „school“ in „s k uh l“). Dies geschieht durch spezielle Algorithmen, die Grapheme in Phoneme umwandeln. Für Sprachen wie Spanisch können einige relativ einfachen Regeln angewendet werden. Aber für andere (z.B. Englisch) unterscheidet sich die Aussprache deutlich von der Schriftform. Statistische Methoden werden dann zusammen mit Datenbanken für bekannte Wörter eingesetzt. Danach ist eine zusätzliche postlexikalische Verarbeitung erforderlich, da sich die Aussprache von Wörtern ändern kann, wenn sie in einem Satz kombiniert werden.

Während Parser versuchen, alle möglichen Informationen aus dem Text zu extrahieren, gibt es etwas, das so schwer zu fassen ist, dass es nicht extrahierbar ist: Prosodie oder Satzrhythmus. Während wir sprechen, verwenden wir Prosodie, um bestimmte Wörter hervorzuheben, Emotionen zu vermitteln und affirmative Sätze, Befehle oder Fragen zu formulieren. Aber geschriebener Text hat keine Symbole, die auf Prosodie hinweisen. Natürlich bieten Satzzeichen einen gewissen Kontext: Ein Komma bedeutet eine kurze Pause, während ein Punkt eine längere Pause angibt, und ein Fragezeichen bedeutet, dass Sie die Tonhöhe gegen Ende eines Satzes anheben. Aber wenn Sie Ihren Kindern jemals eine Gutenachtgeschichte vorgelesen haben, wissen Sie, wie weit diese Regeln vom echten Vorlesen entfernt sind.

Außerdem lesen zwei verschiedene Personen oft den gleichen Text unterschiedlich (fragen Sie Ihre Kinder, wer die Gutenachtgeschichten besser lesen kann – Sie oder Ihr Ehepartner). Aus diesem Grund können Sie statistische Methoden nicht zuverlässig einsetzen, da verschiedene Experten unterschiedliche Bezeichnungen für überwachtes Lernen generieren werden. Dieses Problem ist komplex und trotz intensiver Forschung noch lange nicht gelöst. Das Beste, was Programmierer tun können, ist die Verwendung von SSML. Diese Markupsprache enthält einige Tags für Prosodie.

Neuronale Netze in TTS

Statistische oder Machine Learning-Methoden werden seit Jahren in allen Phasen der TTS-Verarbeitung eingesetzt. Hidden Markov-Modelle werden beispielsweise verwendet, um Parser zu erstellen, die die wahrscheinlichste Analyse generieren, oder um die Bezeichnungen für Sprachprobendatenbanken durchzuführen. Entscheidungsbäume werden bei der Unit Selection oder in Algorithmen für die Umwandlung von Graphemen in Phoneme verwendet, während neuronale Netze und Deep Learning am Rande der TTS-Forschung entstanden sind.

Wir können eine Audioprobe als eine Zeitreihe von Waveform-Sampling betrachten. Durch die Erstellung eines autoregressiven Modells ist es möglich, die nächste Probe vorherzusagen. Dadurch generiert das Modell ein sprachähnliches Blubbern, wie ein Baby, das durch Nachahmung von Geräuschen das Sprechen lernt. Wenn wir dieses Modell weiter auf die Audiotranskription oder die Vorverarbeitung von Ausgaben aus einem vorhandenen TTS-System konditionieren, erhalten wir ein parametrisiertes Sprachmodell. Die Ausgabe des Modells beschreibt ein Spektrogramm für einen Vocoder, der tatsächliche Waveforms generiert. Da dieser Vorgang nicht auf einer Datenbank mit aufgezeichneten Proben basiert, sondern generativ ist, hat das Modell einen geringen Speicherbedarf und ermöglicht die Anpassung von Parametern.

Da das Modell anhand von natürlicher Sprache trainiert wird, behält die Ausgabe alle ihre Eigenschaften, einschließlich Atmung, Betonungen und Intonation (dahe können neuronale Netze das Prosodieproblem potenziell lösen). Es ist auch möglich, die Tonhöhe anzupassen, eine ganz andere Stimme zu erzeugen und sogar Gesang zu imitieren.

Zum Zeitpunkt der Erstellung dieses Artikels bietet Microsoft die Vorschauversion eines neuronalen TTS-Netzwerks (bit.ly/2PAYXWN) an. Es stellt vier Stimmen mit verbesserter Qualität und Leistung nahezu in Echtzeit bereit.

Sprachgenerierung

Da wir nun über die Struktur mit Metadaten verfügen, wenden wir uns der Sprachgenerierung zu. Bei den ursprünglichen TTS-Systemen wurde versucht, Signale durch die Kombination von Sinuskurven zu synthetisieren. Ein weiterer interessanter Ansatz war die Konstruktion eines Systems von Differentialgleichungen, das den menschlichen Stimmapparat als mehrere verbundene Röhren unterschiedlicher Durchmesser und Längen beschreibt. Solche Lösungen sind sehr kompakt, klingen aber leider recht mechanisch. Wie bei Musiksynthesizern verlagerte sich der Fokus allmählich auf Lösungen, die auf Proben basieren, die viel Platz benötigen, aber im Wesentlichen natürlich klingen.

Um ein solches System zu erstellen, benötigen Sie viele Stunden hochwertiger Aufnahmen eines professionellen Sprechers, der speziell konstruierte Texte vorliest. Diese Texte werden in Einheiten (Units) aufgeteilt, bezeichnet und in einer Datenbank gespeichert. Die Sprachgenerierung wird damit zur Aufgabe, die richtigen Einheiten auszuwählen und zu verbinden.

Da Sie Sprache nicht synthetisieren, können Sie die Parameter in der Laufzeit nicht wesentlich anpassen. Wenn Sie sowohl männliche als auch weibliche Stimmen benötigen oder regionale Akzente hinzufügen müssen (z.B. einen schottischen oder irischen Akzent), müssen diese separat aufgenommen werden. Der Text muss so aufgebaut sein, dass er alle möglichen Klangeinheiten abdeckt, die Sie benötigen. Und die Sprecher müssen in einem neutralen Ton lesen, um die Verkettung zu erleichtern.

Das Aufteilen und Kennzeichnen ist ebenfalls keine triviale Aufgabe. Früher wurde es manuell durchgeführt, was wochenlange, mühsame Arbeit erforderte. Glücklicherweise wird dabei inzwischen Machine Learning eingesetzt.

Die Größe der Unit (Einheit) ist wahrscheinlich der wichtigste Parameter für ein TTS-System. Natürlich könnten wir durch die Verwendung ganzer Sätze das natürlichste Klangbild sogar mit der richtigen Prosodie erzeugen, aber so viele Daten aufzunehmen und zu speichern ist unmöglich. Kann eine Aufteilung in Wörter erfolgen? Wahrscheinlich schon, aber wie lange dauert es, bis ein Sprecher ein gesamtes Wörterbuch vorgelesen hat? Und mit welchen Einschränkungen hinsichtlich der Datenbankgröße sind wir konfrontiert? Auf der anderen Seite können wir nicht einfach das Alphabet aufzeichnen – das würde nur für einen Buchstabierwettbewerb reichen. Daher werden Units (Einheiten) in der Regel als zwei Gruppen mit drei Buchstaben ausgewählt. Es handelt sich nicht zwangsläufig um Silben, da Gruppen, die Silbengrenzen überschreiten, viel besser miteinander verbunden werden können.

Jetzt der letzte Schritt. Wenn wir über eine Datenbank mit Spracheinheiten verfügen, müssen wir uns mit der Verkettung befassen. Unabhängig davon, wie neutral die Betonung in der Originalaufzeichnung war, sind beim Verbinden von Units (Einheiten) noch Anpassungen erforderlich, um Sprünge in Lautstärke, Frequenz und Phase zu vermeiden. Dies erfolgt mit DSP (Digital Signal Processing, digitale Signalverabeitung). DSP kann auch verwendet werden, um Sätzen eine gewisse Betonung hinzuzufügen, z.B. das Anheben oder Absenken der generierten Stimme für Aussagen oder Fragen.

Zusammenfassung

In diesem Artikel ging es um nur die .NET-API. Andere Plattformen bieten eine ähnliche Funktionalität. macOS verfügt über NSSpeechSynthesizer in Cocoa mit vergleichbaren Funktionen, und die meisten Linux-Distributionen beinhalten die eSpeak-Engine. Auf alle diese APIs kann über nativen Code zugegriffen werden, sodass Sie C#, C++ oder Swift verwenden müssen. Für plattformübergreifende Ökosysteme wie Python gibt es einige Brücken wie Pyttsx, aber diese weisen in der Regel gewisse Einschränkungen auf.

Cloudanbieter hingegen richten sich an ein breites Publikum und bieten Dienste für die meisten gängigen Sprachen und Plattformen an. Während die Funktionalität herstellerübergreifend vergleichbar ist, kann die Unterstützung für SSML-Tags unterschiedlich sein, daher sollten Sie die Dokumentation vor der Auswahl einer Lösung zu Rate ziehen.

Microsoft bietet einen Text-zu-Sprache-Dienst im Rahmen von Cognitive Services (bit.ly/2XWorku) an. Dieser bietet Ihnen nicht nur 75 Stimmen in 45 Sprachen, sondern ermöglicht es auch, Ihre eigenen Stimmen zu erstellen. Dazu benötigt der Dienst Audiodateien mit einem entsprechenden Transkript. Sie können Ihren Text zuerst schreiben und dann von jemandem lesen lassen, oder Sie verwenden eine vorhandene Aufnahme und erstellen ihr Transkript. Nachdem Sie diese Datasets in Azure hochgeladen haben, trainiert ein Machine Learning Algorithmus ein Modell für Ihren eigenen, einzigartigen „Voicefont“. Eine gute schrittweise Anleitung finden Sie unter bit.ly/2VE8th4.

Eine sehr bequeme Möglichkeit, auf Cognitive Speech Services zuzugreifen, ist die Verwendung des Speech Software Development Kit (bit.ly/2DDTh9I). Es unterstützt sowohl Spracherkennung als auch Sprachsynthese und ist für alle gängigen Desktop- und mobilen Plattformen und die gebräuchlichsten Sprachen verfügbar. Es ist gut dokumentiert, und es gibt zahlreiche Codebeispiele auf GitHub.

TTS ist nach wie vor eine enorme Hilfe für Menschen mit besonderen Bedürfnissen. Besuchen Sie zum Beispiel linka.su, eine Website, die von einem talentierten Programmierer mit Zerebralparalyse erstellt wurde, um Menschen zu helfen, die unter Sprach-, Muskel- und Skeletterkrankungen oder Autismus leiden oder sich von einem Schlaganfall erholen. Aus eigener Erfahrung weiß der Autor, mit welchen Einschränkungen er konfrontiert ist, und hat eine Reihe von Anwendungen für Menschen entwickelt, die nicht Eingaben auf einer normalen Tastatur vornehmen können, die nur einen Buchstaben auf einmal auswählen oder nur ein Bild auf einem Tablet berühren können. Dank TTS gibt er diesen Menschen buchstäblich ihre Stimme zurück. Ich wünsche mir, dass wir alle als Programmierer so hilfreich für andere sein könnten.


Ilia Smirnovverfügt über mehr als 20 Jahre Erfahrung in der Entwicklung von Unternehmensanwendungen auf wichtigen Plattformen, hauptsächlich in Java und .NET. In den letzten zehn Jahren hat er sich auf die Simulation von Finanzrisiken spezialisiert. Er verfügt über drei Master-Abschlüsse sowie über FRM- und andere professionelle Zertifizierungen.

Unser Dank gilt dem folgenden technischen Experten bei Microsoft für die Durchsicht dieses Artikels: Sheng Zhao (Sheng.Zhao@microsoft.com)
Sheng Zhao hat die Position Principal Group Software Engineering bei STCA Speech in Peking inne.


Diesen Artikel im MSDN Magazine-Forum diskutieren