Lokaler Text2Speak (TTS) Server
Ich beschreibe hier meine Vorgehensweise zur Einrichtung eines im lokalen Netzwerk befindlichen TTS-Servers. Dieser kann zum Erstellen von WAV-Sounddateien genutzt werden. Als Eingabe dient der gewünschte Text, den man über eine Webschnittstelle an diesen Server sendet und dann die WAV-Datei anschließend von diesem herunterladen und weiter verwenden kann.
Es gibt diverse Stimmen in vielen Sprachen: https://github.com/rhasspy/piper/blob/master/VOICES.md
Verwendete Softwarekomponenten:
- Debian oder Devuan Linux (minimale Serverversion genügt)
- Webserver mit PHP-CGI (lighttpd)
- Python3 mit PIP
- piper (AI-Sprachgenerierung) => https://github.com/rhasspy/piper
Ich habe einen „neuen“ virtuellen Proxmox Server genutzt. Man kann aber auch einen RasPi oder einen anderen Linuxserver verwenden. Dann muss die Installation der einzelnen Softwarekomponenten evtl. angepasst werden. Ich haben Devuan 4 als Basis verwendet. https://www.devuan.org/
Bei Debian/Deuvan basierten Linuxsystemen wird apt zur Softwareverwaltung verwendet.
Das wird auch bei dieser Anleitung verwendet.
Die folgenden Schritte habe ich als root-User durchgeführt:
Installation des Devuan-Linux bzw. Nutzung eines vorhandenen Linux.
Anschließend Update der aktuellen Software:
apt update
apt upgrade
Installation von python und pip:
apt install python3 pip
Installation von piper:
pip install piper-tts
Test der piper Installation: (Optional)
echo 'Willkommen!' | piper --model de_DE-thorsten-high --output_file welcome.wav
Diese WAV-Datei sollte sich mit einem Player abspielen lassen.
Beim ersten Aufruf von „piper“ wird die benutzte Stimme (hier de_DE_thorsten-high) heruntergeladen und im aktuellen Verzeichnis gespeichert. Die generierte WAV-Datei landet ebenfalls im aktuellen Verzeichnis.
Installation des Webservers mit php-cgi:
apt install lighttpd php-cgi
Aktivierung von PHP fastcgi:
ln -s /etc/lighttpd/conf-available/10-fastcgi.conf /etc/lighttpd/conf-enabled/10-fastcgi.conf
ln -s /etc/lighttpd/conf-available/15-fastcgi-php.conf /etc/lighttpd/conf-enabled/15-fastcgi-php.conf
Neustart des Webservers:
/etc/init.d/lighttpd restart
Damit die heruntergeladene Stimme und die WAV-Datei im WEB-Verzeichnis /var/www/html erstellt werden können, bekommt dieses Verzeichnis Schreibrechte für alle User! Das sollte man bei einem öffentlich erreichbaren Server so nicht tun!
chmod 777 /var/www/html
Im Webverzeichnis /var/www/html wird nun eine kleine PHP-Datei index.php erstellt, die zum Empfang des zu erstellenden Textes dient. Sie ruft dann piper mit den erforderlichen Parametern auf.
/var/www/html/index.php:
<?php
$text = htmlspecialchars_decode($_GET['text']);
$text2 = escapeshellarg($text);
exec("/bin/echo '".$text2."' | /usr/local/bin/piper --model de_DE-thorsten-high --output_file tts.wav");
?>
Nun kann durch den Aufruf des Servers mit Übergabe des Textes eine entsprechende WAV-Datei erstellt werden:
http://server-ip?text=Willkommen
Die WAV-Datei kann anschliessend heruntergeladen werden:
http://server-ip/tts.wav
Im ioBroker nutze ich den Server per JavaScript mit dem Chromecast Adapter.
Der gewünschte Text wird mit dem httpGet() Befehl zum Server übertragen und anschließend die URL der WAV-Datei im Chromecast Adapter im Objekt chromecast.0.Google_Home.player.url2play eingetragen und abgespielt.
Damit das sauber funktioniert, musste ich nach dem Generieren der WAV-Datei eine kleine Pause (1 sec) einfügen, bevor die URL zum Chromecast gesandt wird.
Der Code sieht wie folgt aus:
function talk(text)
{
setState('chromecast.0.Google_Home.player.volume', 30);
setState('chromecast.0.Google_Home.player.announcement', "http://ioBroker-ip:8082/sayit.0/tts.userfiles/mp3_silence_1sec.mp3");
httpGet("http://server-ip/?text="+text, function()
{
setTimeout(function()
{
setState('chromecast.0.Google_Home.player.url2play', 'http://server-ip/tts.wav');
}, 1000);
});
}
Eine Demo für den Webbrowser liefert diese HTML-Datei. Sie bietet neben der Eingabemöglichkeit des Textes auch einen Player zum direkten Abspielen im Browser.
<!doctype html>
<head>
<meta charset=utf-8>
<title>TTS-Demo</title>
</head>
<body>
<?php
$text = htmlspecialchars_decode($_GET['text']);
$text2 = escapeshellarg($text);
exec("/bin/echo '".$text2."' | /usr/local/bin/piper --model de_DE-thorsten-high --output_file play.wav");
?>
<form action="/play.php">
<input type="text" name="text" value="<?php echo $text;?>">
<input type="submit" value="Generate">
</form>
<audio id="audio" controls src="/play.wav"></audio><br>
<a href="/play.wav">Download WAV</a>
<script type="text/javascript">
document.getElementById('audio').addEventListener("ended",function() {
this.src = "/play.wav.php?nocache="+new Date().getTime();
this.play();
});
</script>
</body>
</html>
Evtl. ist das alles für den Einen oder Anderen nützlich.
Tschau
Uwe