#KIWerkstatt

Google bietet verschiedene Dienste im Bereich Analytics und KI / Maschinelles Lernen an. All diese Dienste sind Bestandteile der “Google Cloud Plattform”. 

Im Folgenden beschäftigen wir uns mit der Text-to-Speech API von Google, welche geschriebenen Text in gesprochene Worte synthetisiert. Dieses kann zum Beispiel in der Praxis genutzt werden, um Apps komplett mit Sprachunterstützung auszustatten, Callcenter zu automatisieren oder um IoT-Geräte um Sprachausgabe zu erweitern.  

In diesem Blogartikel werde ich zunächst auf die Vorteile und Besonderheiten von Google Text-to-Speech API eingehen, bevor die API einmal praktisch angewandt wird.

Allgemeines Setup der Text-to-speech API von Google

Zur Verwendung aller oben angegebenen Google-Dienste ist, wie üblich, ein Google-Konto erforderlich. Bitte beachten, dass zur Verwendung sämtlicher Dienste der Google Cloud Plattform ein Konto erforderlich ist, in welchem eine Kreditkarte hinterlegt ist. Sollte noch keine Karte hinterlegt sein, wird die Kartennummer im Freischaltungsprozess für die Plattform abgefragt. 

Zur Freischaltung der 12-monatigen Testphase besuchen wir die entsprechende Seite und befolgen den Prozess, welcher selbsterklärend ist. 

Sollten wir bislang noch keinen Dienst der Google Cloud Plattform verwendet haben, wird uns zu Beginn direkt ein Guthaben in Höhe von 300$ zur Verwendung der Cloud-Dienste zur Verfügung gestellt. 

Unterstütze Sprachen der Text-to-speech API

Google unterstützt derzeit 14 Sprachen mit insgesamt fast 60 unterschiedlichen Stimmen; dabei muss man zwischen den beiden Stimmtypen “Standard” und “WaveNet” unterscheiden.

Während die sogenannte parametrische Sprachausgabe der Standard-Stimmen mit Hilfe von Vocodern generiert wird, wird die Sprachausgabe der WaveNet-Stimmen mit Hilfe eines neuronalen Netzwerkes realisiert.
Da die Vocoder die Stimmen nur anhand von vordefinierten Grammatikregeln und simulierten Mundbewegungen erzeugen, klingen sie oft blechern und unnatürlich bzw. abgehakt. Das ist nachvollziehbar da es enorm schwierig ist, insbesondere die komplexen Mundbewegungen der menschlichen Sprache in einem Algorithmus abzubilden.
Das neuronale Netzwerk hat dieses Problem nicht, da in dem Netzwerk nicht der o.a. Algorithmus hinterlegt werden muss. Stattdessen wurde das Netzwerk mit einer großen Menge von Sprachsamples trainiert. Daher klingen die damit synthetisierten Sprachausgaben natürlicher und sind den menschlichen Stimmen deutlich ähnlicher – obwohl man natürlich noch einen Unterschied feststellen kann. Details dazu siehe hier. Auch die Qualität des generierten Audios ist merklich besser und wirkt flüssiger als bei der parametrischen Sprachausgabe.

Die WaveNet-Stimmen kommen auch bei der Sprachgenerierung für Google Assistant, die Google-Suche und Google Übersetzer zum Einsatz. 

Preise

Google stellt dem Benutzer zur Verwendung der Text-to-Speech API monatliche Kontingente zur Verfügung. Zurzeit liegt dieses für die Verwendung von Standard-Stimmen bei bis zu 4 Millionen Zeichen, für die Verwendung von WaveNet-Stimmen bei bis zu 1 Millionen Zeichen. 

Möchte man die API über das kostenlose Kontingent hinaus verwenden, so kann man das natürlich problemlos tun. Google berechnet dann am Monatsende den zu zahlenden Preis und bucht ihn automatisch von der hinterlegten Kreditkarte ab. Zur Zeit liegt der Betrag für Standard-Stimmen bei 4$ pro angefangene 1 Millionen Zeichen und für WaveNet-Stimmen bei 16$ pro angefangene 1 Millionen Zeichen. 

Datenverarbeitung 

Wie bei Cloud-Diensten üblich ist nicht ohne Weiteres feststellbar, in welchem Land die Daten verarbeitet werden.  

Bei anderen Google Cloud APIs wie z.B. “Cloud Storage” ist definierbar, in welchem Kontinent die Daten liegen sollen. Im Bereich “Cloud Text-to-Speech“ habe ich keine solche Einstellmöglichkeit finden können. 

Insoweit sollte man sich vor Verwendung der API überlegen, ob der Text, welcher in Sprache synthetisiert werden soll, beispielsweise auch rechtlich in die USA übermittelt werden darf (Stichwort DSGVO). 

API-Anbindung 

Um auf die Google Text-to-Speech API von zuzugreifen, stehen verschiedene Möglichkeiten zur Verfügung: Es gibt Client Libraries für C#, Go, Java, Node.JS, PHP, Python und Ruby. Weiterhin gibt es REST- und eine RPC-Anbindung. 

Beispiel zur Einrichtung der Text-to-speech API von Google

Nun wollen wir die API auch einmal praktisch verwenden. 

Voraussetzung für das Nachvollziehen dieses Beispiels ist eine lauffähige Node.JS-Umgebung

Nach der Installation des benötigten NPM-Pakets mittels

npm install --save @google-cloud/text-to-speech

Legen wir die Datei index.js an und füllen sie mit folgendem Inhalt:

const fs = require('fs');
const util = require('util');
const textToSpeech = require('@google-cloud/text-to-speech');
const client = new textToSpeech.TextToSpeechClient(); 

Hiermit werden die benötigten Libraries eingebunden.
Anschließend wird das Request-Objekt zusammengebaut:

const request = {
    input: {
        text: 'Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich'
    },
    voice: {
        languageCode: 'de-DE',
        ssmlGender: 'FEMALE',
        name: 'de-DE-Wavenet-A'
    },
    audioConfig: {
        audioEncoding: 'MP3'
    },
}; 

Fehlt nur noch das Absenden des Requests und das Speichern des Ergebnisses in eine entsprechende Audiodatei. Das erledigen wir mit den folgenden Zeilen: 

(async () => {
    const [response] = await client.synthesizeSpeech(request);
    const writeFile = util.promisify(fs.writeFile);
    await writeFile('output.mp3', response.audioContent, 'binary');
})(); 

Anschließend lassen wir die Datei von Node.JS mittels Kommandozeile interpretieren:

node index.js

Wenn alles wie gewünscht funktioniert hat, erhalten wir am Ende eine Audiodatei (output.mp3) mit dem synthetisierten Text “Zwölf Boxkämpfer jagen Viktor quer über den großen Sylter Deich”. Verwendet wurde dazu die Sprache Deutsch, mit einer weiblichen WaveNet-Stimme. 

Zu beachten ist, dass die Speech-to-Text API tatsächlich nur die Synthetisierung des Textes durchführt. Sie prüft vorher nicht, ob die angegebene Sprache auch korrekt eingestellt wurde. 

Würde man also statt des deutschen Textes einen englischen Text übergeben, würde dieser Text ebenfalls deutsch ausgesprochen. Das würde sich natürlich recht merkwürdig anhören. Daher muss man sich vorher sicher sein, in welcher Sprache der Text vorliegt. 

Wie man weiterhin in dem Request-Objekt sehen kann, ist es möglich, eine SSML-Angabe zu machen. Speech Synthesis Markup Language (SSML) ist eine Auszeichnungssprache speziell für die Synthetisierung von Sprachen. Mit dieser ist es beispielsweise möglich, innerhalb eines Textes Pausen hinzuzufügen.

Verwendet man in seinem Text allerdings keine SSML-Tags, kann man die Option in dem Request-Objekt auch weglassen. 

 Ich habe die index.js-Datei von Node.JS zweimal ausführen lassen. Einmal mit der Stimme “de-DE-Standard-A“ und einmal mit der Stimme “de-DE-Wavenet-A“. 

In der Abbildung sieht man noch einmal die kleinen, aber gut hörbaren Unterschiede zwischen Standard (oben) und WaveNet (unten). 

Abb. 1: Sprachausgabe Standard und WaveNet

Jetzt teilen auf:

7 Comments

  1. Friedrich 5. Mai 2019 at 12:50 - Reply

    Hallo, wo werden im Code die Anmeldedaten hinterlegt?

  2. Marius Panneck 6. Mai 2019 at 9:53 - Reply

    Ebenfalls hallo,
    die Anmeldedaten werden selbst gar nicht im Quellcode hinterlegt.
    Diese muss man über eine Umgebungsvariable im Hostsystem setzen.
    Siehe hier: https://cloud.google.com/text-to-speech/docs/reference/libraries#setting_up_authentication

  3. Friedrich 12. Mai 2019 at 11:03 - Reply

    Danke für deine schnelle Antwort. Wenn du mal viel Zeit hast, mach doch mal ein Tutorial für Dummies. Alle Schritte incl.
    Merci schon jetzt.

  4. Tim 6. September 2019 at 16:43 - Reply

    Guten Tag Herr Panneck,
    ich habe Ihre Anweisungen befolgt und auch die Anmeldedaten in die Umgebungsvariablen gesetzt, leider bekomme ich immer die gleiche Meldung.
    await writeFile(‘output.mp3’, response.audioContent, ‚binary‘);
    ^
    SyntaxError: Invalid or unexpected token
    at Module._compile (internal/modules/cjs/loader.js:723:23)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:789:10)
    at Module.load (internal/modules/cjs/loader.js:653:32)
    at tryModuleLoad (internal/modules/cjs/loader.js:593:12)
    at Function.Module._load (internal/modules/cjs/loader.js:585:3)
    at Function.Module.runMain (internal/modules/cjs/loader.js:831:12)
    at startup (internal/bootstrap/node.js:283:19)
    at bootstrapNodeJSCore (internal/bootstrap/node.js:622:3)
    Haben Sie noch eine Idee.
    Vielen Dank.

    • Marius Panneck 11. September 2019 at 12:14 - Reply

      Vielen Dank für die Nachfrage.
      Diese Meldung sieht mir eher nach einem allgemeinen JavaScript-Fehler aus der nichts explizit mit den Google-Tools zu tun hat.
      Benutzen Sie zur Entwicklung eine spezielle IDE mit JavaScript-Unterstützung (beispielsweise Visual Studio Code)?
      Falls nein, probieren Sie es doch noch einmal damit.
      Falls das auch nicht zur Lösung beiträgt, stellen Sie mir doch gerne einmal ihren gesamten Code zur Verfügung (via https://jsfiddle.net/). In der obigen Zeile allein kann ich keinen Fehler entdecken.
      Beste Grüße
      Marius Panneck

    • Alexander 4. August 2020 at 14:40 - Reply

      Guten Tag Herr Panneck,
      danke für das Tutorial. Bei mir ist derselbe Fehler aufgetreten. Es handelt sich wie vermutet um einem allgemeinen JavaScript-Fehler. Ich musste in der Zeile await writeFile(‘output.mp3’… …) die Apostrophen durch Anführungstriche ersetzen.
      Freundliche Grüße
      Alexander

      • Marius Panneck 5. August 2020 at 10:26 - Reply

        Hallo Alexander,
        vielen Dank für den Hinweis.
        Wir haben den Artikel entsprechend korrigiert.
        Beste Grüße
        Marius Panneck

Jetzt kommentieren