Node Red Speech – The Sequel

Some time ago, I wrote about speech output (text to speech) on the Raspberry Pi using Node Red. Well, that’s been running just fine but like most things – it works until it doesn’t.

In this case the nice people at Google have decided it is time to make money out of the people they offered free language translation APIs to and the API behind the excellent NORMIT program no longer works – I feel sorry for the fellow who spent ages putting it together. Here’s the original article.. https://tech.scargill.net/talking-raspberry/

So, I’ve checked and the best I can come up with for text-to-speech that doesn’t once again rely on someone else’s servers, is “eSpeak”. This is simply installed on your computer as “apt-get install espeak”. I can only vouch for it running on the Raspberry Pi. I tried it on the Radxa Rock yesterday and it failed miserably.

So – I’ve come up with another route.

A program I used which works well, to sound alarms is called mpg123.  (npm install mpg123).  You simply hand it the name of an MP3 file on the command line – and it plays it! http://www.mpg123.de/ for more info.

So yesterday I discovered another service called voicerss (http://www.voicerss.org/) – and you can fire some text at them – and get a streaming MP3 file back!

For example…

http://api.voicerss.org/?key=xxxxxx&src=hello

where xxxxx is the API key they’ll freely give you on application.

So – I wanted this to work in Node-Red from a simple input.  I decided to use msg.payload to carry the text – and reserve msg.topic for the word “alert” if I wanted to prefix the sound with an alarm.

In this version I’ve not implemented complicated queues – I just play the message. See my previous article on queues. These might be needed if you wanted to fire messages out in rapid succession because I’m using Node-Red’s EXEC function and as far as I know – as it fires off things asynchronously – there’s no way to know when jobs are done. I guess you could have it run a batch file which sets and clears some kind of flag – I’ll leave that to others.

Here’s the basic setup.

tmpEAD1

What you see above – is a simple inject node – with the word “alert” in the topic (optional) and some text in the payload – for example “hello how are you”.

The function in the middle does all the work – the EXEC node at the end simply has “mpg123” as the command – other boxes are defaults.

Here are the internals of “THING” in the middle.

if (msg.payload.indexOf(“.mp3”)!=-1) return (msg); // if payload is an mp3 just play it, nothing else
    if (msg.topic.indexOf(“alert”)!=-1)
    {
    var msg2 = {
                payload : “”,
                topic : “”
                };
        msg2.topic=msg.topic;
        msg2.payload=’/usr/audio/alert02.mp3′;
        node.send(msg2); // possibly play an alert
    }
    var moment=context.global.moment;
    var timeadd=””;
    var dateadd=””;
    if (msg.topic.indexOf(“time”)!=-1)
      timeadd= moment().format(“h:mm a “)+ ‘, ‘;
    if (msg.topic.indexOf(“date”)!=-1)
      dateadd= moment().format(“dddd, MMMM Do YYYY”)+ ‘, ‘;
     
    msg.payload = msg.payload.replace(/”/gi, “‘”);
    msg.payload = msg.payload.replace(/’/gi, “””);   
    msg.payload= ” -q ‘http://api.voicerss.org/?key=XXXXXXXX&src=” + dateadd + timeadd + msg.payload + “‘”;
    node.send(msg); // synth   

Where you see XXXXXX above – put your API key from api.voicerss.org

You’ll note I have a file called /usr/audio/alert02.mp3 in there as well –  you can change the name and location but you should grab a suitable short alert mp3 sound from somewhere. I got it off a trekkie site.

As detailed in the original blog you’ll need to install and include MOMENT  if you want to be able to put “time” or “date” into the topic and have that spoken – if not just miss that stuff offf.

Below is a version with no time and date stuff.

 

if (msg.payload.indexOf(“.mp3”)!=-1) return (msg); // if payload is an mp3 just play it, nothing else
    if (msg.topic.indexOf(“alert”)!=-1)
    {
    var msg2 = {
                payload : “”,
                topic : “”
                };
        msg2.topic=msg.topic;
        msg2.payload=’/usr/audio/alert02.mp3′;
        node.send(msg2); // possibly play an alert
    }
     
    msg.payload = msg.payload.replace(/”/gi, “‘”);
    msg.payload = msg.payload.replace(/’/gi, “””);   
    msg.payload= ” -q ‘http://api.voicerss.org/?key=XXXXXXXX&src=”  + msg.payload + “‘”;
    node.send(msg); // synth   

Have fun.

11 thoughts on “Node Red Speech – The Sequel

  1. Good job guys. I was very sad after Normit stopped working. What a great plugin it was.But I knew If I came here,
    Pete and the Gang would be scrambling to find a replacement. I did find Ivona the other day but was not able to get any sound from the mp3. But again with everyone’s help with setting up the credentials the right way I was able to hear once again. 🙂 I think Ivona is going to be a great replacement for Google. The voices sound great.
    Thanks Everyone.

  2. This might sound daft, but try the following to ensure that no escape characters (e.g. tab) are being pasted into the password.
    – Paste the copied key value from the website into a text editor first – and then copy the value from the text editor into node-red. I find that a tab character slips ito the first character every now and then

    1. Woah, that is VERY good – way better than anything I’ve come across before. What’s more, the EXEC function has an output that operates when the speech is finished – and deletes the speech file. With care I can feed speech into a queue and check for absence of file before proceeding with the next item.

      Very good – thanks for your help Pete. I’ll blog this when it is working – I have it talking – and deleting the file but I need it to handle sequential requests…

  3. The reviews like IVONA, I hope you can get it working.

    If you want something that can run on the Pi, I found a few folks who liked the SVOX Pico TTS engine that’s part of Android. This is the install for Wheezy – http://rpihome.blogspot.com/2015/02/installing-pico-tts.html
    The author couldn’t get it to install on Jessie but the last commentor gave some links to some packages he claims will work for Jessi.

    1. Yup got Ivona working – that was easy – not so easy was getting it to do multiple speech items in sequence – done that now – when I get a moment I’ll document the lot.

  4. Yes – all looking good – just put the value seen for “secret key” into the node-red “password”.
    However, as you’ve probably found out, you can only make a note of the “secret key” once – when you first create the credentials!

    The other “delete” commands in the node may not be needed for R.PI. I had to use this dummy delete, so the “Requesting” light changed. If this bogus delete exec wasn’t there, then the node hung with a yellow light

    1. Ok, did all that, well, it SEEMED to work, used /home/pi/pete.mp3 as the path.. and it generated a 1k .MP3 file no matter how long text I send to it – and mpg123 says it is playing it – but no audio comes out… something wrong there, I’d expect a file with a full sentence to be way bigger than that. SO I read the file….

      {“Message”:”Authentication failed”}

  5. Not an alternative – but I found the IVONA node generates decent speech files (in alternative languages too!). Perhaps you could use something like this to capture the MP3 speech files?
    You could use the IVONA flow example in the Node-red “examples” page or alternatively, the flow below could be used (It has been adapted to work on “WINDOWS” with “VideoLAN”).
    “VideoLAN” plays the MP3 files and I’ve set up some config in “VideoLAN” to collapse the session after playing the audio).

    EXAMPLE FLOW FOR IVONA NODE
    (N.B. I’ve messed about with the credentials so some set up is required )

    [{“id”:”dac176b9.6577b8″,”type”:”ivona-credentials”,”name”:”IVONA Credentials”,”api_key”:”IVONA_DUMMY_API_KEY”,”password”:”IVONA_PASSWORD”},{“id”:”d0f9833a.504468″,”type”:”debug”,”name”:””,”active”:true,”console”:”false”,”complete”:”payload”,”x”:593,”y”:523,”z”:”e8ee9f2c.53443″,”wires”:[]},{“id”:”d1b46670.8acf48″,”type”:”ivona-tts”,”name”:””,”message”:”{{payload}}”,”voice”:”6″,”exec”:”del C:\\Users\\YOUR_USER_DIRECTORY\\pete1.mp3″,”dir”:”Pete.mp3″,”broker”:”dac176b9.6577b8″,”x”:271,”y”:428,”z”:”e8ee9f2c.53443″,”wires”:[[“261303ce.c29654”]]},{“id”:”95b4dc8b.5be18″,”type”:”exec”,”command”:”del C:\\Users\\YOUR_USER_DIRECTORY\\pete.mp3″,”addpay”:true,”append”:””,”useSpawn”:””,”name”:”Delete”,”x”:436,”y”:535,”z”:”e8ee9f2c.53443″,”wires”:[[“d0f9833a.504468”],[],[]]},{“id”:”261303ce.c29654″,”type”:”exec”,”command”:”\”C:\\Program Files (x86)\\VideoLAN\\VLC\\vlc.exe\” –one-instance –intf dummy C:\\Users\\YOUR_USER_DIRECTORY\\pete.mp3″,”addpay”:false,”append”:””,”useSpawn”:””,”name”:”VLC”,”x”:278,”y”:535,”z”:”e8ee9f2c.53443″,”wires”:[[],[“95b4dc8b.5be18”],[]]},{“id”:”c2943cfc.a5deb8″,”type”:”inject”,”name”:””,”topic”:””,”payload”:”Hello World”,”payloadType”:”string”,”repeat”:””,”crontab”:””,”once”:false,”x”:87,”y”:418,”z”:”e8ee9f2c.53443″,”wires”:[[“d1b46670.8acf48”]]}]

    1. Ok Pete – I tried this… but I’m doing something wrong – so I grabbed a set of credentials from their website…. I put the node into Node Red (I’m using a PI not a PC) – and I may have the credentials wrong as I did the following: Added an INJECT node with “hello there” in the payload. I set up credentials – it wanted my name, my API key and password. For name I used my real name – assuming this was not important. API key I gave it the API key. Password was not so clear.. I used the password I used to log into their service. Is it that or should I have used the secret key???

      Anyway I understand when you press go it generates a temporary MP3 and that’s fine as I can pass that via EXEC to MPG123 – but I got as far as “requesting” and it stays there. Did I get some part of the credential setup wrong?

    1. A very good reason.. I DO use eSpeak (see original article) – but it sounds horrible:-) I was looking for alternatives. Also I could not get eSpeak to install on other systems like the Rock, although it does install easily on the Pi2.

Comments are closed.