We have moved at community.getvera.com

Author Topic: Amazon Polly TTS alternative approach  (Read 4038 times)

Offline Thanster

  • Newbie
  • *
  • Posts: 8
  • Karma: +1/-0
Amazon Polly TTS alternative approach
« on: June 27, 2017, 02:42:24 pm »
Like many of you, I've struggled to find a decent TTS engine for Sonos after Microsoft ended their TTS service.  As a parent of toddlers, I quickly noticed I wasn't getting notified whenever the kids opened the doors and left the house. 

I went looking for a fast, high-quality service and I settled on Amazon Polly.  It's free for the first year and then $4 per million characters after that.  Given my use cases are limited to door and gate notifications I expect to pay less than $4/year after the first year.

This solution is external to Vera, but I've found it works well and integrates nicely with the VeraAlerts plugin that I was already using.

It uses a Rasberry Pi and a Node.js module named: Sonos HTTP API http://jishi.github.io/node-sonos-http-api/

This approach completely bypasses the Vera Sonos plug-in but the two play nicely with one another.  In VeraAlerts I set up a new "URL" alert and used the syntax: http://RaspberryPi/sayall/{Msg}

As a bonus the Sonos HTTP API locally caches, so routine announcements like door notifications start playing almost instantly.

Hope this info helps someone.

Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #1 on: July 17, 2017, 02:25:06 pm »
Hi

Is there a way for that service to be called by Vera itself (scene/lua code/api) - so you can send the required text in the required format to your PI for that node.js app to play it via your Sonos ?? E.g...

Code: [Select]
luup.inet.wget("http://raspberrypi/sayall/{this+is+my+message+Msg}")
« Last Edit: July 17, 2017, 02:32:50 pm by parkerc »

Offline kapstaad

  • Sr. Newbie
  • *
  • Posts: 49
  • Karma: +2/-0
Re: Amazon Polly TTS alternative approach
« Reply #2 on: July 18, 2017, 11:31:25 pm »
Quote
I went looking for a fast, high-quality service and I settled on Amazon Polly.

I'd like to say a big "Thank you!" for this info; it took me a couple of hours of not particularly hard work; I setup an AWS account, configured it for credentialed access to Polly, added nodejs and npm 8.x to my Raspbian Jessie Pi, configured the api node, and have since converted all of my spoken system messages to use Polly's "Joanna" voice. Works great!  Thank you!  :D

Offline kapstaad

  • Sr. Newbie
  • *
  • Posts: 49
  • Karma: +2/-0
Re: Amazon Polly TTS alternative approach
« Reply #3 on: July 18, 2017, 11:38:12 pm »
Hi

Is there a way for that service to be called by Vera itself (scene/lua code/api) - so you can send the required text in the required format to your PI for that node.js app to play it via your Sonos ?? E.g...

Code: [Select]
luup.inet.wget("http://raspberrypi/sayall/{this+is+my+message+Msg}")

I've had issues with luup.inet.wget() -- it seems quirky about how it receives input (urlencoded or not) so I ended up using the socket.http method instead which worked out great:

local code = 404
local _, code, _ = http.request("http://192.168.1.xxx:5050/sayall/This is a test of Amazon Polly/Joanna/45")
-- note, polly default port is 5050

Good luck! ;)

Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #4 on: July 19, 2017, 01:38:51 am »
Many Thanks @kapstaad

Looking at your code, is it ok for the text part of the http.request to include spaces - does it not need to use '+' instead  ?

Also I followed your earlier link to the software's website but could not find anything about the URL / POST structure to invoke TTS externally (e.g from Vera) - would you be able to direct me to exactly where that section is?

Offline mvader

  • Sr. Member
  • ****
  • Posts: 397
  • Karma: +29/-75
Re: Amazon Polly TTS alternative approach
« Reply #5 on: July 19, 2017, 10:36:09 am »
I did something similar. using polly, but instead of cloud-rendering on the fly, i wrote a cache system, so after is speaks a phrase, it's cached and no re-rendering is needed.
it's not like saying "the garage door is open" is going to change. so why render every time. cache and then play the cached file.
I do really like the whole aws and polly system. its well developed and has a ton of options.

Offline jswim788

  • Hero Member
  • *****
  • Posts: 809
  • Karma: +58/-2
Re: Amazon Polly TTS alternative approach
« Reply #6 on: July 24, 2017, 08:06:05 pm »
I did something similar. using polly, but instead of cloud-rendering on the fly, i wrote a cache system, so after is speaks a phrase, it's cached and no re-rendering is needed.
it's not like saying "the garage door is open" is going to change. so why render every time. cache and then play the cached file.
I do really like the whole aws and polly system. its well developed and has a ton of options.
Would you be willing to share more details about how you did this or even some of the code?  It sounds interesting.  Thanks!
« Last Edit: July 24, 2017, 10:47:48 pm by jswim788 »

Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #7 on: July 25, 2017, 06:32:54 am »
Found this online as a way to create standalone (Polly created) mp3s.

https://ericheikes.com/text-speech-tool-aws-polly/

Offline kapstaad

  • Sr. Newbie
  • *
  • Posts: 49
  • Karma: +2/-0
Re: Amazon Polly TTS alternative approach
« Reply #8 on: July 25, 2017, 03:59:42 pm »
Many Thanks @kapstaad

Looking at your code, is it ok for the text part of the http.request to include spaces - does it not need to use '+' instead  ?

The text part can contain spaces if you're using http.request; it works, so I'd guess (too lazy/busy to check docs :P) that http.request does it's own urlencoding internally.

Quote
Also I followed your earlier link to the software's website but could not find anything about the URL / POST structure to invoke TTS externally (e.g from Vera) - would you be able to direct me to exactly where that section is?

Documentation for the Node.js widget I'm using is here:

https://github.com/jishi/node-sonos-http-api#say-tts-support

Here's the lua code I'm using:

Code: [Select]
function Polly(phrase, vol, zone, voice)
 
  local http    = require "socket.http"; socket.http.TIMEOUT = 3
  local server  = "192.168.1.xxx" -- change to your own Vera device local IP
  local port    = "5005" 
 
  if(voice == nil) then voice = "Joanna" end
  if(vol == nil) then vol = 50 end
  if((zone == nil) or (zone == "ALL")) then zone = "sayall" else zone = zone .. "/say" end
  local polly = "http://" .. server .. ":" .. port
  local purl  = polly .. "/" .. zone .. "/" .. phrase .. "/" .. voice .. "/" .. vol
 
  local _, code, _ = http.request(purl)
 
  if(code ~= 200) then
    writelog("Call to Polly failed: result code (" .. code .. ")")
  end
 
end

example:

Code: [Select]
Polly("This is a test of Polly, the Amazon speech engine.", 60") -- plays in all zones at 60% volume
when called, the function assembles the following URL, and calls it:

http://192.168.1.xxx:5005/sayall/This is a test of Polly, the Amazon speech engine./Joanna/60

Hope this helps :)
« Last Edit: July 25, 2017, 04:02:07 pm by kapstaad »

Offline Spanners

  • Sr. Member
  • ****
  • Posts: 265
  • Karma: +16/-5
Re: Amazon Polly TTS alternative approach
« Reply #9 on: July 27, 2017, 11:16:16 pm »
I have this working now. Running the node-sonos-http-api in a Docker container on my QNAP NAS.

I do like the caching feature, makes repeat standard announcements very snappy. The Polly voices are a bit underwhelming considering there's a similar technology underpinning Alexa.

One handy tip for using VeraAlerts with the URL profile. Make sure you delete the "undefined" field for MessagePrefix. I was getting nowhere with VeraAlerts triggering the sonos api until I specifically blanked that field.

« Last Edit: July 27, 2017, 11:18:44 pm by Spanners »

Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #10 on: July 29, 2017, 05:33:51 pm »
I have this working now. Running the node-sonos-http-api in a Docker container on my QNAP NAS.

Hi @Spanners

I like the idea of running it as Docker and I have a QNAP too..

To help me, would you be able to share the 'Advanced Settings' that you've used ? E.g Do you run it NAT, Bridge, Host ? I'm not too familiar with Container Statation.

Update : I've installed it under network settings 'NAT', which makes the service available via "192.168.1.111:32768" which I think then forward to port 5005 based on what the console is showing. Not sure that is correct..

Update2 : Ok found out it will not work using NAT, so have changed to 'Bridge' which allows it get its own IP and use port 5005. (I understand this is because it requires multicast traffic as well as inbound and outbound connections)

@Spanners - where do you go to add/edit the required files set up Polly with the Docker? E.g the Location of 'settings.json'?
« Last Edit: July 29, 2017, 08:41:39 pm by parkerc »

Offline Spanners

  • Sr. Member
  • ****
  • Posts: 265
  • Karma: +16/-5
Re: Amazon Polly TTS alternative approach
« Reply #11 on: July 29, 2017, 11:27:13 pm »
Hi @parkerc

I have the node-sonos-http-api running in a container using Bridge networking. I have ha-bridge running in another container on Host, but plan to move it to Bridge when I get the time.

To manipulate the files in the containers, I didn't find an easy way to do it (QNAP dropped the ball a bit here I feel with Container Station). What you need to do is SSH into your QNAP and use these commands:

docker ps

That will give you the unique ID of the containers running. Then use

docker cp <source> <destination>

to copy files in and out of the container. Recommend using the Public share on your QNAP, as containers have limited access. I used:

docker cp dccd7fa3c88e:/app/settings.json /share/Public/
docker cp /share/Public/settings.json dccd7fa3c88e:/app/

To copy the file out, edit it on the share and copy it back in. I guess you could use the advanced container settings to mount a volume you can externally access or something, but haven't explored it.




Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #12 on: July 30, 2017, 03:03:57 am »
Thanks so much @spanners

I have ha bridge and Home Assistant dockers running in 'bridge' mode and 'host' respectively. Containers just seem a great way to add extras functionality (but the hosting technology is not easy to get your head around)

FYI - I did a file search last night across  my entire Qnap for key files e.g server.js (in the hope I might find the location where the source files for this particular docker are kept) - and I think I may have found something...

Code: [Select]
find . -name server.js
It took me to to location that i seem to recall had been set up as my virtual container/VM storage location, which was a share called.. Backups/VM/

Code: [Select]
share/Backups/VM/container_station_data/lib/docker/devicemapper/mnt/08abcderfghitygh45444665ggf/rootfs/app/
... I edited the index.html file in the /static/ subfolder of the above and that updated the Sonos Http API web page that you access via http://Your_IP:5005

I would be interested to here if you think that is the location where the Sonos http api docker's install files are stored?

Also please could you share a redacted copy of your settings.json file ?
« Last Edit: July 30, 2017, 04:38:22 am by parkerc »

Offline parkerc

  • Beta Testers
  • Sr. Hero Member
  • *****
  • Posts: 2479
  • Karma: +35/-48
  • Life Moves Pretty Fast....
Re: Amazon Polly TTS alternative approach
« Reply #13 on: July 30, 2017, 05:44:43 am »
Success a Sunday morning well spent.

I have Polly up and running; I'm able to upload files directly to the container via the location I mentioned above. And rather than use lua code to construct the required URL; as the app knows what to do, the following seems to do the job (The IP is the one for your sonos-http-api server/Docker)

This is for all zones

Code: [Select]
http://192.168.1.167:5005/sayall/This%20is%20a%20test%20of%20Polly,%20the%20Amazon%20speech%20engine./Joanna/60
This is for just one zone (kitchen)

Code: [Select]
192.168.1.167:5005/kitchen/say/This%20is%20a%20test%20of%20Polly,%20the%20Amazon%20speech%20engine./Joanna/60
My settings.json is here

Code: [Select]
{
  "aws": {
    "credentials": {
      "region": "eu-west-1",
      "accessKeyId": "ADRT14NOTMINE1727/23",
      "secretAccessKey": "idnenshdbhebxiukdbeanyrhing/ezuT7ZSag"
    },
    "name": "Joanna"
  }
}

Which is placed here..

Code: [Select]
./share/CACHEDEV1_DATA/Backups/VM/container-station-data/lib/docker/devicemapper/mnt/994asastart08abcderfghitygh45444665ggf/rootfs/app/settings.json
« Last Edit: August 27, 2017, 06:11:04 pm by parkerc »

Offline BOFH

  • Sr. Hero Member
  • ******
  • Posts: 2409
  • Karma: +112/-140
Re: Amazon Polly TTS alternative approach
« Reply #14 on: July 30, 2017, 10:49:28 am »
Thank you so much for posting your Amazon Polly credentials so we can can use it for free.  8)

Seriously though, you may want to blank those out ASAP to avoid possible abuse.
Vera3 UI5 UI7 Edge Plus
Trane TZEMT400AB32 | Schlage BE369 FE599 | GE 45601 45602 45603 45604 45606 45609 45631 | Intermatic HA01C HA03C HA05C HA07C CA600 CA3000 | Aeon DSC06106 | Telguard GDC1 | Foscam FI8910W FI8905W FI9821W | D-Link 930L | Wanscam JW0011 | ZModo ZPIBH13W