Begriffe wie Smart Home, Hausautomatisierung und Internet of Things (IoT) tauchen mittlerweile überall auf und man kommt eigentlich nicht mehr an diesen Themen vorbei. Im Rahmen der Hausautomatisierung habe ich nach einer unabhängigen Lösung gesucht, um eine dynamische Sprachausgabe zu realsieren. Diese soll unabhängig von der eingesetzten Hausautomatisierungsanlage wie z.B. Homematic, KNX o. ä. lauffähig sein.

Lösungsansatz

Ein möglicher Lösungsansatz war relativ schnell gefunden. Da bereits ein Raspberry Pi für andere Aufgaben läuft, sollte dieser auch diese Aufgabe übernehmen.

Voraussetzungen

  • Raspberry Pi (mit z. B. Raspbian)
  • HTTP Webserver (z. B. Lighttpd und PHP Suport)
  • Programmiersprachen: Python & PHP

Realisierung

1. Text-to-Speech Dienst auswählen

Um über den Raspberry Pi eine dynamische Sprachausgabe zu ermöglichen, muss dieser um eine Text-to-Speech (TTS) Funktionalität erweitert werden. Es gibt einige Anwendungen und Online-Services die dafür verwendet werden können. Diese unterscheiden sich aber oft deutlich in der Qualität der Aussprache. Aus diesem Grund ist meine Wahl auf folgende zwei TTS-Services gefallen

Google Text-to-Speech (Online Dienst)
Der Online TTS Dienst des Google Übersetzer ist vielen bekannt. Dieser bietet die Möglichkeit, einen eingegeben Text vorzulesen. Zusätzlich funktioniert es auch, die Sprachausgabe über eine einfache HTTP-Anfrage (GET-Request) anzufordern. Es wird dann eine MP3 Datei zurückgeliefert, welche die Sprachausgabe enthält.

SVOX Pico TTS (Offline Anwendung)
Weitere Informationen zu diesem Sprachsynthesizer findet Ihr in einem anderen Blog-Eintrag von mir.
Text mit SVOX Pico TTS direkt von der Kommandozeile oder aus einer Datei durch Sprachausgabe wiedergeben

2. Pi-To-Speech Service (Python-Script)

Um die Erzeugung der Audio-Datei für die Sprachausgabe zu automatisieren, habe ich ein kleines Phython-Script entwickelt, welches aktuell die genannten TTS-Dienste unterstützt.

Den Sourcecode für das Python-Script gibt es auf GitHub:
pi-to-speech-service.py

Cache
Das Script bietet die Möglichkeit die erzeugte Audiodatei lokal zu speichern. Wird erneut der gleiche Text angefragt, muss dann die Audiodatei nicht neu erzeugt werden. Hier wird dann einfach die zuvor gespeicherte Datei verwendet. Dies bietet neben der Performance-Optimierung auch den Vorteil, dass nicht unnötig der einer Text-to-Speech Services angefragt werden muss.

Google Limitierung
Bei der Verwendung des Google Text-to-Speech Dienstes ist die Limitierung auf max. 100 Zeichen pro Anfrage. Im Script wurde das Problem gelöst, indem ein längerer Text in jeweils 100 Zeichen aufgeteilt wird und mehrere Anfragen erfolgen.

Script ausführen
Um über das Pyhton-Script den Text „Hallo“ in eine Sprachausgabe umzuwandeln, kann dies wie folgt ausgeführt werden:

 python tts-service.py --text "Hallo" --provider "google" 

Hinweis: Weitere mögliche Parameter und deren Beschreibungen findet man im GitHub Repository.

3. Webservice für Zugriff im Netzwerk

Um das Script auch von „außerhalb“ der Kommandozeile aufrufen zu können, habe ich zusätzlich ein kleines PHP-Script erstellt. Da auf meinem Raspberry Pi bereits ein HTTP-Webserver (Lighttpd) mit PHP Unterstützung läuft, konnte ich das PHP-Script einfach darüber bereitstellen und innerhalb des lokalen Netzwerkes aufrufen.

Den Sourcecode für das PHP-Script gibt es auf GitHub:
tts-service.php

Benutzerberechtigung
Zu beachten sind hierbei die Benutzerberechtigungen. Diese Einstellungen können natürlich je nach Konfiguration, Pfad, Benutzernamen etc. abweichen und müssen individuell angepasst (auch im PHP-Script) werden.

Möglickeit 1:
Mein Benutzer für den Webserver hat keine Berechtigung um das Pyhton-Script auszuführen.
Hierfür wurde ein eigener Benutzer „tts“ erstellt. Zusätzlich muss dann in der Datei „/etc/sudoers“ eine Anpassung für die Berechtigung vorgenommen werden.

 www-data ALL=(tts) NOPASSWD: /opt/tts/pi-to-speech-service.py 

Möglickeit 2:
Will man keinen Benutzer anlegen, dann kann auch für Python das Set User ID (SetUID) Bit gesetzt werden.

sudo chmod u+s /usr/bin/python

Dann ist es nicht mehr notwendig im PHP-Script das Python-Script mittels ’sudo -u‘ zu starten.
Diese kleine Anpassung muss dann im PHP-Script noch vorgenommen werden.

Sicherheit
Alle internen Webservices befinden sich im Ordner „internal“. Da solche Services nicht von überall aufgerufen werden dürfen, habe ich zusätzlich die Lighttpd Konfigurationsdatei „/etc/lighttpd/lighttpd.conf“ erweitert. Folgende Bedingung prüft, ob es sich beim Aufrufer um ein Gerät im internen Netzwerk handelt, ansonsten wird der Zugriff verweigert.

$HTTP["remoteip"] !~ "192\.168\.1\.*" {
  $HTTP["url"] =~ "^/(internal)/" {
    url.access-deny = ( "" )
  }
}

Script ausführen
Ist alles korrekt eingerichtet, kann das PHP-Script folgendermaßen aufgerufen werden.

http://<SERVER-IP>/internal/tts.php?text=hallo&provider=google

Hierbei können auch alle durch das Pyhton-Script unterstützte Parameter verwendet werden.

Längere Texte
Da es für die URL eine maximale Länge gibt, besteht für längere Texte die Möglichkeit, diesen über den Body als POST-Request zu senden.

Dynamische Sprachausgabe mittels Pi-To-Speech Service – Mein Raspberry Pi lernt sprechen (mit Hilfe von Google TTS und Pico TTS)

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.