GoogleTTS responding with 503 error (even after the URL fix)

voicerss seems to be gone…

as an alternative, i managed to install picotts locally using this instructions.

http://blog.robotnet.de/2014/03/25/speak-friend-and-enter-speech-synthesis-with-espeak-and-svox-pico-for-the-raspberry-pi/

seems ok.

@Nicola_Reina This looks pretty interesting. to my mind having a local TTS engine seems like a good idea.

Do you have any details of how you handled the integration with Openhab. i.e. did you somehow configure it to read urls and return a wav like the google TTS service, or did you do it some other way.

BTW I Stumbled across some info about installing on Jessie and that these packages are now available:

https://packages.debian.org/jessie/all/libttspico-data/download
https://packages.debian.org/jessie/armhf/libttspico0/download
https://packages.debian.org/jessie/armhf/libttspico-utils/download

if you add the following to your sources.list:
deb http://ftp.de.debian.org/debian jessie main non-free

you can apt-get them, seems to work ok.

I completely agree - a local TTS service makes a lot more sense. VoiceRSS is working ok in my test setup (sorry it is a very busy time of year I haven’t had a chance to code it up properly yet) but the delay is noticeable, especially when announcing long sentences that have to handled in two requests (VoiceRSS only allows up to 100 chars per request).

I am going to look into a ttspico and see if I can get that working. Would love to be free of these online services!

Hi I installed it locally using the instructions at the link .
I have not yet integrated it but in the end it could just be a matter of using exec binding…
I mean you do not have to have any wav file you just pass the sentence to speak to the command and… it speaks

Hey guys,

I spent some time today playing around with pico2wave and building a simple PHP script to replicate what the Google TTS service does. Had some reasonable success, instructions below.

You should be able to run this on a local server (using apache or the like) and then point your Google TTS binding to this URL. It expects two parameters in the URL - language (e.g. en-GB) and message to translate.

Installation

  • install the necessary dependencies (pico2wave, lame)
    • sudo apt-get install libttspico0 libttspico-utils libttspico-dev libttspico-data lame
  • install PHP composer (needed to install/use phplame)
  • copy the two files attached here to a folder under /var/www
    • e.g. /var/www/tts
    • ensure your web server has sufficient permissions to create files in this directory (e.g. owned by www-data)
  • run composer to resolve the necessary dependencies
    • sudo composer install
  • setup your web server to allow requests to /var/www/tts
    • beyond the scope of these instructions
  • test by typing in the following to your browser;

I am using this in my hacked Squeezebox speak action (which I have hardcoded to call this URL) and it is nice and quick and the GB voice is quite fluid and sounds really good IMO.

Let me know if this helps!
Ben

tts.pdf (810 Bytes)

This file is actually a ZIP, so rename the extension to .zip and extract the two files to your /var/www/tts folder.

I’ve been playing with this as well over the last few days. I’m quite happy with the pico2wave results. I did this with a rule instead which I’ll share for those interested. Again pico2wave and lame need to be installed. First a lambda expression to replace squeezeboxSpeak

val org.eclipse.xtext.xbase.lib.Functions$Function3 squeezeSay = [
    String playerID,
    String message,
    int volume |
            executeCommandLine("pico2wave@@--wave=/tmp/openhab.wav@@"+message)
            Thread::sleep(500)
            executeCommandLine("lame@@-V2@@/tmp/openhab.wav@@/tmp/openhab.mp3")
            Thread::sleep(500)
            squeezeboxPlayUrl(playerID,"/tmp/openhab.mp3",volume) ]

then just replace squeezeboxSpeak with squeezeSay.apply ie:

squeezeSay.apply("mainPlayer","My Message",20)

Make sure the directory you use (in my case /tmp) can be reached by both openhab and the logitech media server. If openhab is running on a faster computer, you may be able to decrease the sleep times. The only downside is that squeezeboxPlayUrl does not have a resume function.

I have just create a pull request with some changes to the Squeezebox io and action bundles to allow TTS URL configuraton. Note that I have removed the language config option as this is just a parameter in the TTS URL. The URL just needs a single %s parameter which is substituted with the text to be translated. I have also updated the openhab_default.cfg with details about the new configuration options.

1 Like

Using these updated Squeezebox io and action bundles, along with my tts.php script from above, I now have entirely local TTS notifications with no reliance on any cloud services.

Ben, how is the lag time doing it locally? Do you have the tts on the same box as openhab or another local network box?

The delay is barley noticeable using my local TTS service, my notifications are almost instant now. I am running the TTS service on a different VZ container than the openHAB container (but on the same physical host).

FYI - my changes to the Squeezebox action have been merged so if you grab the latest SNAPSHOT build you can test these changes out (you will need both the io.squeezserver and action.squeezebox bundles).

Added a page to the WIKI with these details;

3 Likes

What changes are needed to make openHAB use the new TTS provider for rules and such? I have the setup working as you describe. I can test TTS with success in my browser passing the URL example you have given, but when I define my Google TTS url within openhab.cfg, it doesn’t seem to work. I do get audio, but it seems to be only the last file or test I used via the browser test example and not the actual strings being passed by openhab. For example, I have a test rule to fire every 2 mins and announce the time. when it runs now, it repeats “hello” as used in the test string: http://172.16.0.51/tts/tts.php?lng=en-GB&msg=Hello.

I can see the following in the logs when I intentionally make it throw an error:

2015-12-29 16:12:00.057 [WARN ] [.i.m.i.tts.TTSServiceGoogleTTS] - Error while connecting to Google translate service
java.io.FileNotFoundException: http://172.16.0.51/tts/tts.php?lng=en-GB&msg=en

This shows me it’s only passing “en” to the server and not the actual string.

Any thoughts or insight would be awesome! Thanks!

The Google TTS service substitutes two parameters into the URL - the first is the language (defaults to ‘en’) and the second is the text to be spoken.

So you will probably need to update your TTS URL to;

http://172.16.0.51/tts/tts.php?lng=%s&msg=%s

And then specify your Google TTS language as en-GB.

That did the trick! I thought I had tried it specified like that, but maybe not. In any case, it’s working like a charm. Many thanks!

I’m really pleased with the new local TTS solution Ben has described. It’s running quite well for the last four days. Thanks!

1 Like

yeah, this is huge in my opinion. I never liked the idea of TTS relying on the cloud. All the other solutions just don’t sound polished enough. I utilize TTS over “whole home audio/multi zone audio” and it has been less then ideal with the previous setup.

If anyone is curious, a fella named Mat who wrote up a really cool bit about a $40 rack mount, 12x12 input/output audio control device called the XAP 800. It ties perfectly into openHAB, and facilitates room by room voice control with it’s “gating” features and GPIO :slight_smile: Think killing music playing to play an alert or notification among other things…
Here’s the link: http://hazymat.co.uk/2015/04/multi-room-audio-options/.

With TTS working much better now, and some good zoned audio/voice control, my home is really starting to sound and work like a smart home lol.

Yep @hazymat has done some pretty awesome work, in particular with Squeezeboxes + openHAB. His MQTT based wall controller is very cool - check out his blog for more details.

I have been using the local TTS service for about a week now and am finding it very good. Can’t see me ever going back to a cloud based service now.

Glad others are finding this useful as well.

1 Like

Thanks for the mention @ben_jones12! Wow - local TTS using Squeezebox? This is awesome. My announcements using Google TTS were reliable for a while, then less-so, then altogether stopped working - I couldn’t be bothered to look into it, but I shall use this. Thanks for your excellent work!

@jbags81 (and others) may be interested to know that I didn’t end up using the GPIO port of the XAP, but rather I’m using the serial port, and addressing it from OpenHAB. Haven’t written this up on my blog yet, but I’ll paste below an example config for addressing the XAP from OpenHAB.

You need a USB to serial (RS232) cable, I got mine for a couple of quid on eBay.

The below is quite basic, it simply switches the audio input for a given zone (in this case the bedroom) from one stereo source to another.

There are four commands in the rule for each time I switch an audio source, see rule below. Imagine a matrix with an x that marks a mapping. Each time you switch an output you need to remove an x from the matrix, and add an x elsewhere. That’s two actions. Then times by two because it’s a stereo source.

Check out Appendix E of the user guide (http://www.clearone.com/uploads/resource/800_151_101_Rev4_1_XAP800Man.pdf)

I set up the XAP using the Windows software so that it had device number 1. The format in the above doc says you need to feed it with this:

#DEVICE COMMAND [X] [X]

#DEVICE = 51 = the device type of the XAP800 which is always 5, and the device number you set (i.e. 1 in my case)

The command is MTRX, meaning you want to edit the matrix, i.e. you want to map or unmap something to / from something. The MTRX command is documented on page 118, that’s how I came up with the below.

OpenHAB settings:

Items:
Number Bedroom_Audio_Source
String XAP800

Rules:
rule “Bedroom Source”
when
Item Bedroom_Audio_Source received command
then
switch(receivedCommand) {
case 0 : {
sendCommand(XAP800, “#51 MTRX 11 I 1 O 1 \n”)
sendCommand(XAP800, “#51 MTRX 12 I 2 O 1 \n”)
sendCommand(XAP800, “#51 MTRX 9 I 1 O 0 \n”)
sendCommand(XAP800, “#51 MTRX 10 I 2 O 0 \n”)
}
case 1 : {
sendCommand(XAP800, “#51 MTRX 9 I 1 O 1 \n”)
sendCommand(XAP800, “#51 MTRX 10 I 2 O 1 \n”)
sendCommand(XAP800, “#51 MTRX 11 I 1 O 0 \n”)
sendCommand(XAP800, “#51 MTRX 12 I 2 O 0 \n”)
}
}
end