Wetterberichte selbst erstellen

In diesem Artikel geht es um die automatische Generierung von gesprochenen Wetterberichten auf Basis des Open Data Angebotes des deutschen Wetterdienstes und von Googles Cloud Text-to-Speech API. Der deutsche Wetterdienst stellt im Rahmen seines Open Data Angebots textbasierte Wetterberichte für eine Vielzahl von Bundesländern bereit. Das hier vorgestellte Python-3-Skript verwendet diese Texte als Basis für die Generierung eines auf Sprachsynthese basierenden gesprochene Wetterberichtes.

Das folgende Beispiel gibt einen Eindruck über die Sprach und Textqualität des synthetisch erzeugten Wetterberichtes:

Vorraussetzungen

Für die Ausführung des Skriptes wird Python, ein gültiges JSON Schlüsselfile für Googles Text-To-Speech API und eine Internetverbindung benötigt.

Projekt herunterladen

Das Projekt "Synthetischer Wetterbericht" wird bei GitHub gehostet. Eine lokale Kopie des Projektes kann durch eingabe der folgenden Zeile in der Kommandozeile erstellt werden:

git clone https://github.com/beltoforion/Synthetischer-Wetterbericht.git

Notwendige Python Bibliotheken

Das Skript benötigt eine Python Installation. Zusätzlich müssen die Google cloud text-to-speech Bibliotheken installiert werden. Deren Installation erfolgt mittels pip, dem Standard Paketmanager für Python, durch Eingabe des folgenden Befehls:

pip install --upgrade google-cloud-texttospeech

Sollte es bei der Installation von google-cloud-texttospeech Probleme geben, die auf eine fehlende Installation der Python setup tools hinweisen, so können diese mit folgendem Befehl nachinstalliert werden (gilt nur für Debian basiertes OS).

sudo apt-get install python3-setuptools

Schlüsseldatei für Google Clouds Text-To-Speech beschaffen

Die Schlüsseldatei ist nicht Teil des Quellcodearchives! Cloud Text-To-Speech ist ein kostenpflichtiges API von Google, dessen Nutzung nur mit gültigen Schlüsseldateien bzw. API-Keys möglich ist. Für die Nutzung stellt Google jedoch monatlich Freikontingente bereit (Stand 2019; kostenfrei bis 1 Million Zeichen pro Monat). Um diese Freikontingente Nutzen zu können und eine Schlüsseldatei zu erstellen ist eine Anmeldung bei der Google Developer Console erforderlich.

Programmbeschreibung

Das Skript erstellt immer einen Wetterbericht für die nächsten drei Tage. Die Ausführung des Programmes erfolgt aus der Kommandozeile. Es werden folgende Kommandozeilenargumente unterstützt:

Parameter Beschreibung
-k Pfad zur JSON Schlüsseldatei für Google Cloud Text-To-Speech.
Das Programm funktioniert nur mit gültiger Schlüsseldatei!
-o Name der Ausgabedatei. Die Ausgabe erfolgt immer im MP3 Format. Wenn der Parameter weggelassen wird, erfolgt die Ausgabe in die Datei "output.mp3"
-s Bundesland bzw Region. Folgende Regionen werden unterstützt: 'Sachsen', 'Sachsen-Anhalt', 'Thüringen', 'Berlin', 'Mecklenburg-Vorpomern', 'Brandenburg', 'Niedersachsen', 'Bremen', 'Hamburg', 'Rheinland-Pfalz', 'Bayern', 'Hessen', 'Saarland', 'Baden-Würtenberg', 'Schleswig-Holstein', 'Nordrhein-Westfalen'
-wave Wenn dieser Parameter vorhanden ist, werden die WaveNet Stimmen verwendet. WaveNet Stimmen haben eine deutlich höhere Qualität, sind aber auch teurer bzw. haben ein geringeres Freikontingent.
-nowarn Wenn dieser Parameter vorhanden ist, werden die Teile im Bericht über die allgemeine Wetterlage, die sich explizit mit Warnwetterlagen (Gewitter, Strum, Frost usw.) beschäftigen ignoriert. Das ist das empfohlene Verhalten. In den Wetterberichten für die einzelnen Tage werden solche Wetterlagen ohnehin erwähnt.

Der hier gezeigte Befehl generiert eine gesprochen Wettervorhersage ohne explizite Wetterwarnungen mit WaveNet-Stimmen (hohe Qualität) für das Wetter der nächsten drei Tage in Sachsen:

python3 wetterbericht.py -k ~/google_api_keys/text-to-speach-key.json -o wetter.mp3 -s Sachsen -wave -nowarn

Funktionsweise

Das Programm läd automatisch die in HTML vorliegenden Wetterberichte des DWD für eine bestimmte Region herunter und wandelt diese in eine SSML-Datei um. SSML ist eine HTML ähnliche Beschreibungssprache für Textausgaben. Formulierungen, die als Sprachausgabe keinen Sinn ergeben werden herausgefiltert. Zusätzlich werden Sprechpausen zwischen den einzelnen Teilen des Wetterberichtes eingefügt.

Abschließend wird die SSML Datei an Googles Text-To-Speech Dienst geschickt. Dort wird sie in eine, mit einer computergenerierten Stimme gesprochen Sprachdatei umwandelt. Die Qualität der Sprachsynthese ist mittlerweile so hoch, dass man nur noch schwer den Unterschied zu einer menschlichen Stimme erkennen kann. Die Wetterberichte können entweder mit den Basisstimmen oder mit den besseren WaveNet Stimmen eingesprochen werden.

Die Wetterberichte des DWD

Die Wetterberichte können vom Opendata-Server des DWD in Form von HTML-Fragmenten heruntergeladen werden. Dokmentationen zu Datenstruktur und dem Dateinhalt stellt der DWD unter der URL https://www.dwd.de/DE/leistungen/opendata/hilfe.html bereit.

Die HTML-Fragmente befinden sich im Verzeichnis https:/opendata.dwd.de/weather/text_forecasts/html Die Daten sind nach Bundesländern bzw. Regionen und Vorhersagetag geordnet. Region und Vorhersagezeitpunkte sind in den Dateinamen kodiert.

Die Dateinamen folgen der Konvention: VHDL$WAS$_DW$WO$_LATEST.html, wobei $WAS$ ein Code ist, der Zeitpunkt bzw. Typ der Vorhersage spezifiziert und $WO$ ein Regionscode ist.

Region Regionscode ($WO$)
Nordrhein-Westfalen EH
Bremen und Niedersachsen HG
Hamburg und Schleswig-Holstein HH
Sachsen LG
Sachsen-Anhalt LH
Thüringen LI
Nordbayern MO
Bayern MS
Hessen OH
Rheinland-Pfalz und Saarland OI
Berlin und Brandenburg PG
Mecklenburg-Vorpommern PH
Baden-Würtenberg SG
In Dateinamen verwendete Regionscodes.
Code Bedeutung ($WAS$)
50 Wettervorhersage für heute
51 Wettervorhersage für morgen
52 Wettervorhersage für übermorgen
53 Wettervorhersage für über-übermorgen
54 Gesamtwetterlage
Verwendete Zeitcodes.

Der Wetterbericht für Sachsen (Regionscode LG) für heute und die nächsten 3 Tage befindet sich beispielsweise in folgenden Dateien:

Bei dem Format der einzelnen Fragmente handelt es sich um einfaches HTML:
<strong>Letzte Aktualisierung: 28.05.2019, 22.34 Uhr</strong>
<pre style="font-family: sans-serif">
Ausgehend von einem Tiefdruckkomplex über Skandinavien fließt mit einer westlichen Strömung feuchte und wieder etwas kühlere Meeresluft nach Sachsen. 
Den Osten des Freistaats streift dabei zunächst noch ein Regengebiet eines Tiefs über Polen. 

Es werden keine warnrelevanten Wettererscheinungen erwartet.
</pre>

Nachbearbeitung der Texte

Die Dateien enthalten im Original einige Begriffe und Formulierungen, die für die Sprachausgabe nicht geeignet sind. Aus diesem Grund werden die Texte wie folgt nachbearbeitet.

Ungewollte Maßeinheiten

Angaben von Windgeschwindigkeiten werden entfernt, wenn sie in Klammern stehen.

Beispiel für Text mit ungewollten Einheiten:
... Hagel und Sturmböen um 70 km/h (Bft 8).

Warnwetterlagen

Die Texte zur allgemeinen Wetterlage können bei Auftreten warnrelevanter Wetterereignisse Abschnitte für verschiedene Warnwetterlagen enthalten. Die Abschnitte enthalten die Warnwetterlage als Überschrift, gefolgt von einem Doppelpunkt. Diese Teile des Wetterberichtes können mit der Kommandozeilenoption "-nowarn" ignoriert werden.

Wenn die Option nicht gesetzt ist, so werden die Wetterwarnungen mitgesprochen. Dadurch kann sich der Wetterbericht auf über drei Minuten verlängern. Überschriften werden generell nicht mitgesprochen und durch kurze Sprechpausen ersetzt.

Beispiel für Text mit warnrelevante Wetterlagen:
Zwischen einem Tief nördlich der Britischen Inseln und einem Hoch über Osteuropa fließt mit einer südlichen Strömung 
sehr warme bis heiße und zu Gewittern neigende Luft ein. Von Westen her greift allmählich ein Tiefausläufer auf die 
Region über.

UNWETTER/GEWITTER/STARKREGEN/STURM:
Bis in die erste Nachthälfte zum Dienstag hinein in der Nordwesthälfte einzelne starke Gewitter mit Starkregen um 
15 l/qm in kurzer Zeit, kleinkörnigem Hagel und Sturmböen um 70 km/h (Bft 8). In der Prignitz eng begrenzt schwere 
Gewitter (Unwetter) mit heftigem Starkregen über 25 l/qm innerhalb kurzer Zeit, Hagel um 3 cm und teils schweren 
Sturmböen zwischen 85 und 100 km/h (Bft 9-10). Mit geringer Wahrscheinlichkeit auch in Südbrandenburg und im Berliner 
Raum einzelne Gewitter. In der zweiten Nachthälfte zum Dienstag abklingende Gewitteraktivität.

STURM/WIND:
Am Abend und in der ersten Nachthälfte im Nordwesten und im Berliner Raum in Rahmen einer Böenlinie auch abseits 
von Gewittern auftretende Wind- bis Sturmböen zwischen 50 und 75 km/h (Bft 7-8) aus West bis Nordwest. 

HITZE:
Tagsüber starke Wärmebelastung.

Fehlen warnrelevante Wetterlagen so befindet sich anstelle dessen häufig der Satz "Es werden keine warnrelevanten Wettererscheinungen erwartet." im Text. Dieser und ähnliche Sätze werden ebenfalls aus dem einzusprechenden Text entfernt.

Bekannte Sprachfehler der KI umgehen

Bestimmte wiederkehrende Formulierungen der Wetterberichte werden von der KI des Sprachsyntheseprogrammes falsch ausgesprochen. Wörter, bei denen bekannt ist, das die KI sie nicht richtig ausspricht werden so umgeschrieben, dass die Aussprache korrigiert wird. Das betrifft derzeit nur wenige Worte.

Bekannt sind Sprachfehler in den Worten "Landesteilen", wo das "st" nicht richtig ausgesprochen wird und im Wort "Südost", wo die Betonung des "o" falsch ist. Das betrifft im wesentlichen zusammengesetzte Wörter und kann leicht durch getrennt schreiben der Wörter behoben werden.

Konvertierung in SSML

Die nachbearbeiteten Inhalte der einzelnen Dateien kann man kombinieren und leicht in ein SSML-Dokument konvertieren. SSML ist eine vom W3C definierte Beschreibungssprache für synthetisierte Sprachausgabe, die HTML ähnelt. Das Ergebnis nach Filterung und Kombination der Ausgangsdateien ist der komplette Wetterbericht als SSML-Dokument.

<speak>
<p>
Ausgehend von einem Tiefdruckkomplex über Skandinavien fließt mit einer West- bis Nordwestströmung etwas kühlere Meeresluft 
nach Brandenburg und Berlin. Am Mittwoch setzt sich vorübergehend Hochdruckeinfluss durch.
</p>
<break time="0.3s"/>
<p>
Im Süden letzte Schauer, von Nordwesten her Auflockerungen. Am Mittwoch heiter. In der Nacht zum Donnerstag häufig Frost in 
Bodennähe.
<break time="0.4s"/>
In der Nacht zum Mittwoch anfangs stark bewölkt, von Berlin bis in die Niederlausitz letzte Schauer. Auch im Fläming zeitweise 
leichter Regen nicht ausgeschlossen. Von Nordwesten her bereits größere Auflockerungen, in der zweiten Nachthälfte teils gering 
bewölkt und verbreitet niederschlagsfrei. Tiefstwerte zwischen 8 und 5 Grad. Schwacher Wind aus nördlichen Richtungen.
</p>
<break time="0.3s"/>
<p>
Am Mittwoch neben Quellwolken viele heitere Abschnitte, nur in den südlichen Landesteilen am Vormittag noch teils dichtere 
Wolkenfelder. Gegen Abend gebietsweise wolkenlos. Durchweg trocken. Höchstwerte zwischen 15 und 18 Grad. Meist schwacher Wind aus 
Nordwest, gegen Abend aus unterschiedlichen Richtungen. In der Nacht zum Donnerstag gering bewölkt, teils klar, niederschlagsfrei. 
Abkühlung auf 5 bis 2 Grad, in Bodennähe häufig Frost, örtlich bis -3 Grad. Schwacher Wind aus unterschiedlichen Richtungen, gegen 
Morgen aus Südost.
</p>
</speak>

Googles Text-To-Speech API

Anfragen an das Text-To-Speech API können mit wenigen Zeilen Quellcode formuliert werden. Die hier gezeigte Klasse TextToSpeech basiert auf den von Google bereitgestellten Quellcodebeispielen und demonstriert den Zusammenbau einer Anfrage an den Google-Server.

class TextToSpeech:
    _keyFile = ""
    _useWaveNet = True;

    def __init__(self, keyfile: str, useWaveNet: bool):
        self._keyFile = keyfile
        self._useWaveNet = useWaveNet

    def text_to_speech(self, text, file_name):
        credentials = service_account.Credentials.from_service_account_file(self._keyFile)
        client = texttospeech.TextToSpeechClient(credentials=credentials)

        # Auswahl der Inputmethode (SSML) und übergeben des Inhaltes der SSML Datei
        synthesis_input = texttospeech.types.SynthesisInput(ssml=text)

        # Auswahl der Sprache und der zu verwendenden Stimme
        if (self._useWaveNet):
            voice = "de-DE-Wavenet-B"
        else:
            voice = "de-DE-Standard-B"

        voice = texttospeech.types.VoiceSelectionParams(
            language_code='de',
            name=voice
        )

        # Auswahl der zu erzeugenden Ausiodatei
        # https://cloud.google.com/text-to-speech/docs/reference/rest/v1beta1/text/synthesize#VoiceSelectionParams
        audio_config = texttospeech.types.AudioConfig(
            pitch=-1,
            speaking_rate = 1,
            audio_encoding=texttospeech.enums.AudioEncoding.MP3)

        # Ausführung der Text-To-Speech Anfrage mit ausgewählter Stimme und Audiokonfiguration
        response = client.synthesize_speech(synthesis_input, voice, audio_config)

        # Schreiben der Ausgabedatei
        with open(file_name, 'wb') as out:
            out.write(response.audio_content)
            print('Audio content written to file {0}'.format(file_name))

In dem Quellcodebeispiel wird eine SSML-Datei an den Google-Server übertragen und die erhaltenen MP3-Datei mit dem synthetisch eingesprochenen Wetterbericht lokal gespeichert.