Logic Machine Forum
Amazon Polly - Printable Version

+- Logic Machine Forum (https://forum.logicmachine.net)
+-- Forum: LogicMachine eco-system (https://forum.logicmachine.net/forumdisplay.php?fid=1)
+--- Forum: Scripting (https://forum.logicmachine.net/forumdisplay.php?fid=8)
+--- Thread: Amazon Polly (/showthread.php?tid=756)



Amazon Polly - bmodeco - 25.04.2017

Hi,
I did some testing with voicerss for text-to-speech but i find that the quality insufficient.
I would like to use amazon aws Polly but I don't know how to authenticate when using the http-api.
The idea would be to also to get an mp3 back just like with voiceless.
Anyone who can help me with this?
Thanks, Bart


RE: Amazon Polly - gjniewenhuijse - 26.04.2017

(25.04.2017, 20:43)bmodeco Wrote: Hi,
I did some testing with voicerss for text-to-speech but i find that the quality insufficient.
I would like to use amazon aws Polly but I don't know how to authenticate when using the http-api.
The idea would be to also to get an mp3 back just like with voiceless.
Anyone who can help me with this?
Thanks, Bart

hello, did you have the voicerss service working? can you please share your code?


RE: Amazon Polly - bmodeco - 26.04.2017

(26.04.2017, 07:27)gjniewenhuijse Wrote:
(25.04.2017, 20:43)bmodeco Wrote: Hi,
I did some testing with voicerss for text-to-speech but i find that the quality insufficient.
I would like to use amazon aws Polly but I don't know how to authenticate when using the http-api.
The idea would be to also to get an mp3 back just like with voiceless.
Anyone who can help me with this?
Thanks, Bart

hello, did you have the voicerss service working? can you please share your code?

Hi,
Will post it tonight. The mp3 is saved (through ftp) om my synology-nas so that all my sonos-speakers have access to the mp3.
I have it currently setup so that my music (when playing) pauses, plays the mp3 and then continues were it left of.
don't know if this is what you are looking for.
I am using this for my doorbell also: pushbutton connected to knx-input, triggers a script that pauses music (when playing), plays the doorbell sound (or a barking dog if you want Big Grin ) and continues afterwards.
I wanted to convert this to amazon polly but I don't know how to do the authentication (creation of signature/hash-stuff) when using the http-api.
Amazon Polly has lots of options: parts of text louder or even whispering, parts of text faster or slower...

Check this link for hearing the voices: https://aws.amazon.com/polly/details/
They sound very lifelike...(even dutch female/male voice)
Br,
Bart


RE: Amazon Polly - bmodeco - 26.04.2017

Hi Admin,
Any ideas on how to do the authentication for the http api of aws amazon polly?
Should be similar to what you are doing with amazon alexa...
Thanks, Bart


RE: Amazon Polly - admin - 27.04.2017

I can try and provide a sample but I don't have anything to test it with. If you can setup Polly on your AWS account and PM the details then I can see what I can do Smile


RE: Amazon Polly - bmodeco - 27.04.2017

(27.04.2017, 05:53)admin Wrote: I can try and provide a sample but I don't have anything to test it with. If you can setup Polly on your AWS account and PM the details then I can see what I can do Smile

Hi admin,
I did send you a PM with the info to access my aws Polly.
Thanks again,
BR, Bart


RE: Amazon Polly - admin - 02.05.2017

Here's an example on how to access Amazon Polly. Make sure you set region, accesskey, secretkey and voice variables correctly.

This has been tested on the latest RC1 firmware, but you also need to install package updates to have support for sha256 function:
Standard LM: https://dl.openrb.com/misc/luaencdec_20170426_mxs.ipk
LM power version: https://dl.openrb.com/misc/luaencdec_20170426_imx6.ipk

Code:
function getpollyurl(text)
  -- CONFIG VARIABLES
  local region = 'eu-west-1' -- your AWS region
  local accesskey = 'xxx'
  local secretkey = 'yyy'
  local voice = 'Joey' -- list of voices: https://aws.amazon.com/polly/details/

  -- same as JS encodeURIComponent
  local function encode(str)
    return (str:gsub("[^%w%-_%.%!%~%*%'%(%)]", function(c)
      return string.format("%%%02X", c:byte(1,1))
    end))
  end

  function toquerystring(items)
    local res = {}
    for _, item in ipairs(items) do
      res[ #res + 1 ] = item[ 1 ] .. '=' .. encode(item[ 2 ])
    end
    return table.concat(res, '&')
  end

  function getkey(key, datestamp, regionname, servicename)
    local kdate = encdec.hmacsha256(datestamp, 'AWS4' .. key, true)
    local kregion = encdec.hmacsha256(regionname, kdate, true)
    local kservice = encdec.hmacsha256(servicename, kregion, true)
    return encdec.hmacsha256('aws4_request', kservice, true)
  end

  local encdec = require('encdec')
  local method = 'GET'
  local service = 'polly'
  local host = service .. '.' .. region .. '.amazonaws.com'
  local api = '/v1/speech'
  local endpoint = 'https://' .. host .. api
  local amzdate = os.date('!%Y%m%dT%H%M%SZ')
  local datestamp = os.date('!%Y%m%d')
  local algorithm = 'AWS4-HMAC-SHA256'
  local canonicaluri = api
  local canonicalheaders = 'host:' .. host
  local signedheaders = 'host'
  local credentialscope = datestamp .. '/' .. region .. '/' .. service .. '/' .. 'aws4_request'
  local canonicalquerystring = toquerystring({
    { 'OutputFormat', 'mp3' },
    { 'Text', text },
    { 'TextType', 'text' },
    { 'VoiceId', voice },
    { 'X-Amz-Algorithm', algorithm },
    { 'X-Amz-Credential', accesskey .. '/' .. credentialscope },
    { 'X-Amz-Date', amzdate },
    { 'X-Amz-SignedHeaders', signedheaders },
  })
  local payloadhash = encdec.sha256('')
  local canonicalrequest = table.concat({
    method,
    api,
    canonicalquerystring,
    canonicalheaders,
    '',
    signedheaders,
    payloadhash
  }, '\n')
  local stringtosign = table.concat({
    algorithm,
    amzdate,
    credentialscope,
    encdec.sha256(canonicalrequest)
  }, '\n')
  local signingkey = getkey(secretkey, datestamp, region, service)
  local signature = encdec.hmacsha256(stringtosign, signingkey)

  return endpoint .. '?' .. canonicalquerystring .. '&X-Amz-Signature=' .. signature
end

url = getpollyurl('testing polly from logic machine')

require('ssl.https')
res, status = ssl.https.request(url)
if res then
  -- res contains the mp3 file
else
  alert('Polly request failed: ' .. tostring(status))
end



RE: Amazon Polly - bmodeco - 02.05.2017

(02.05.2017, 06:10)admin Wrote: Here's an example on how to access Amazon Polly. Make sure you set region, accesskey, secretkey and voice variables correctly.

This has been tested on the latest RC1 firmware, but you also need to install package updates to have support for sha256 function:
Standard LM: https://dl.openrb.com/misc/luaencdec_20170426_mxs.ipk
LM power version: https://dl.openrb.com/misc/luaencdec_20170426_imx6.ipk

Code:
function getpollyurl(text)
 -- CONFIG VARIABLES
 local region = 'eu-west-1' -- your AWS region
 local accesskey = 'xxx'
 local secretkey = 'yyy'
 local voice = 'Joey' -- list of voices: https://aws.amazon.com/polly/details/

 -- same as JS encodeURIComponent
 local function encode(str)
   return (str:gsub("[^%w%-_%.%!%~%*%'%(%)]", function(c)
     return string.format("%%%02X", c:byte(1,1))
   end))
 end

 function toquerystring(items)
   local res = {}
   for _, item in ipairs(items) do
     res[ #res + 1 ] = item[ 1 ] .. '=' .. encode(item[ 2 ])
   end
   return table.concat(res, '&')
 end

 function getkey(key, datestamp, regionname, servicename)
   local kdate = encdec.hmacsha256(datestamp, 'AWS4' .. key, true)
   local kregion = encdec.hmacsha256(regionname, kdate, true)
   local kservice = encdec.hmacsha256(servicename, kregion, true)
   return encdec.hmacsha256('aws4_request', kservice, true)
 end

 local encdec = require('encdec')
 local method = 'GET'
 local service = 'polly'
 local host = service .. '.' .. region .. '.amazonaws.com'
 local api = '/v1/speech'
 local endpoint = 'https://' .. host .. api
 local amzdate = os.date('!%Y%m%dT%H%M%SZ')
 local datestamp = os.date('!%Y%m%d')
 local algorithm = 'AWS4-HMAC-SHA256'
 local canonicaluri = api
 local canonicalheaders = 'host:' .. host
 local signedheaders = 'host'
 local credentialscope = datestamp .. '/' .. region .. '/' .. service .. '/' .. 'aws4_request'
 local canonicalquerystring = toquerystring({
   { 'OutputFormat', 'mp3' },
   { 'Text', text },
   { 'TextType', 'text' },
   { 'VoiceId', voice },
   { 'X-Amz-Algorithm', algorithm },
   { 'X-Amz-Credential', accesskey .. '/' .. credentialscope },
   { 'X-Amz-Date', amzdate },
   { 'X-Amz-SignedHeaders', signedheaders },
 })
 local payloadhash = encdec.sha256('')
 local canonicalrequest = table.concat({
   method,
   api,
   canonicalquerystring,
   canonicalheaders,
   '',
   signedheaders,
   payloadhash
 }, '\n')
 local stringtosign = table.concat({
   algorithm,
   amzdate,
   credentialscope,
   encdec.sha256(canonicalrequest)
 }, '\n')
 local signingkey = getkey(secretkey, datestamp, region, service)
 local signature = encdec.hmacsha256(stringtosign, signingkey)

 return endpoint .. '?' .. canonicalquerystring .. '&X-Amz-Signature=' .. signature
end

url = getpollyurl('testing polly from logic machine')

require('ssl.https')
res, status = ssl.https.request(url)
if res then
 -- res contains the mp3 file
else
 alert('Polly request failed: ' .. tostring(status))
end

Hi admin,
Thanks a lot! I can confirm that it works as expected on RC1...
BR, Bart