TTS Engine Custom - Amazon Polly - 24 languages

Make sure the polly code is in /var/www/html/admin/modules/tts/agi-bin/propolys-tts.agi, any changes in the GUI will overwrite the code.

So, every time I click Submit on the TTS I am trying to create it wants me to apply config; but, everytime I do that it resets the above file. So how am I actually supposed to create the TTS?

Comment from a developer. The line

case 'node'

Should not be node. That’s a very broad and generic term. It should be

case 'amazonpolly'
1 Like

Changing the file /var/lib/asterisk/agi-bin/propolys-tts.agi however in the GUI will appear in red that the file was modified because it is not part of the original code.

I’m configuring in version 14 because those tests were made in version 13 and I do not know if something changed, I’ll need a few minutes.

Works fine with FreePBX 14!

propolys-tts.agi,“Olá, bem vindo a central de serviços da Volts Engenharia.”,node,/usr/bin/node: Text to speech wave file doesnt exist, lets create it.
propolys-tts.agi,“Olá, bem vindo a central de serviços da Volts Engenharia.”,node,/usr/bin/node: Executing node
> 0x7feef8574ac0 – Strict RTP learning complete - Locking on source address 192.168.15.34:8000
propolys-tts.agi,“Olá, bem vindo a central de serviços da Volts Engenharia.”,node,/usr/bin/node: Streaming the generated wave.
<SIP/2000-00000189> Playing ‘tts/node-tts-84f3d34e02700ce4b3c495f832201d87.slin’ (escape_digits=#) (sample_offset 0) (language ‘en’)
– <SIP/2000-00000189>AGI Script propolys-tts.agi completed, returning 4

    default;
            $format = array(
                    "ext" => "sln",
                    "rate" => "8000"
            );
    break;

Change to

    default;
            $format = array(
                    "ext" => "wav",
                    "rate" => "8000"
            );
    break;

Alright, had to grab something to eat. So I have re-entered both the engine case, which I have renamed to ‘aws-polly’ and also the default format array for wav files. I saved those changes. I renamed the engine in Settings >> Text to Speech Engines to ‘aws-polly’. And then I created a TTS and submitted it, but I have NOT clicked on apply config. Where do i go to see if this was successful? Is it printed in a log file that the file has been made?

You need to change the case in propolys to aws-polly and apply the settings in the TTS GUI. You can monitor the logs in the Asterisk CLI and also in /var/lib/asterisk/sounds/tts/

In my tests I created an incoming route with the number 0800 with destination for the TTS and a 2000 extension changed the context of the extension to from-pstn and I call the 0800 to test

Yes, I did that. I don’t know how to copy all of the code when it goes off the screen, forgive me, this is what i have…

    default;
            $format = array(
                    "ext" => "wave",
                    "rate" => "8000"
            );
    break;

AND

    switch ($engine) {
            case 'text2wave':
                    exec($enginebin." -f ".$format['rate']." -o $tmpwavefil$
                    break;
            case 'flite':
                    exec($enginebin." -f $textfile -o $tmpwavefile");
                    break;
            case 'swift':
                    exec($enginebin." -p audio/channels=1,audio/sampling-ra$
                    break;
            case 'pico':
                    exec($enginebin." -o $tmpwavefile ".escapeshellarg(file$
                    break;
            case 'aws-polly':
                    exec($enginebin." /opt/aws-nodejs-sample/script.js --mp$
                    break;
            default:
                    debug("$engine is not a valid engine!", 1);
            break;
    }

When I call into the PBX, I get the following in Asterisk Log Files…

[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] pbx.c: Executing [1@ext-tts:4] AGI(“SIP/callcentric1-00000002”, “propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node”) in new stack
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: Launched AGI Script /var/lib/asterisk/agi-bin/propolys-tts.agi
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: TTS AGI Started
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: Generated WAV file: /var/lib/asterisk/sounds/tts/node-tts-d895f2aab26eed89285064a40c6245d0.wave
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: TXT file: /var/lib/asterisk/sounds/tts/node-tts-d895f2aab26eed89285064a40c6245d0.txt
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: Text to speech wave file doesnt exist, lets create it.
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: Executing node
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: node is not a valid engine!
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: File was not created!
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: propolys-tts.agi,“The number you are calling has been successfully routed through The Clever Crib IP PBX. This call will now be terminated!”,node,/usr/bin/node: TTS AGI end
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] res_agi.c: <SIP/callcentric1-00000002>AGI Script propolys-tts.agi completed, returning 0
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] pbx.c: Executing [1@ext-tts:5] Goto(“SIP/callcentric1-00000002”, “app-blackhole,hangup,1”) in new stack
[2017-09-29 19:41:44] VERBOSE[13736][C-00000002] pbx_builtins.c: Goto (app-blackhole,hangup,1)

But all that happens is the call is answered and then hungup, which happens right after the TTS.

You have changed the name to aws-polly but the engine is still a “node”, review the settings in the FreePBX GUI

WORKING SUMMARY:

  1. Run these commands in shell:
cd /opt/
git clone https://github.com/awslabs/aws-nodejs-sample
cd aws-nodejs-sample
npm install
npm install optimist
npm install child_process

2a) Create file in directory /opt/aws-nodejs-sample/

vim script.js

// Load the SDK
var argv = require('optimist').argv;
const AWS = require('aws-sdk')
const Fs = require('fs')
var child_process = require('child_process');
// Create an Polly client
const Polly = new AWS.Polly({
accessKeyId: "accessKeyId here",
secretAccessKey: "secretAccesKey here",
signatureVersion: 'v4',
region: 'us-east-1'

})

let params = {
'Text': argv.text,
// 'Text': 'Tatiana',
'OutputFormat': 'mp3',
'SampleRate': '8000',
'VoiceId': 'Amy'
}

Polly.synthesizeSpeech(params, (err, data) => {
if (err) {
console.log(err.code)
} else if (data) {
if (data.AudioStream instanceof Buffer) {
Fs.writeFile(argv.mp3, data.AudioStream, function(err) {
if (err) {
return console.log(err)
}
console.log("The file was saved!")
var output = child_process.execSync('lame --decode ' + argv.mp3 + ' ' + '-b 8000' + ' ' + argv.wav + '.wav');

        })
    }
}
})

2b) You can change the voice, by going to google and typing “Amazon Polly Available Voices”. Sorry but new users cant post links here.

Then copy the Name/ID you want and replace ‘Amy’ in the ‘VoiceId’ line above with that ID.
Also, DO NOT FORGET to obtain and enter your AWS ‘accessKeyId’ and ‘secretAccessKey’ in the lines marked bold above!

3a) Modify /var/lib/asterisk/agi-bin/propolys-tts.agi to change the following lines:

vim /var/lib/asterisk/agi-bin/propolys-tts.agi

FROM

    default;
            $format = array(
                    **"ext" => "sln",**
                    "rate" => "8000"
            );
    break;

TO

    default;
            $format = array(
                    **"ext" => "wav",**
                    "rate" => "8000"
            );
    break;

3b) Continue modifying the same file to add the following lines to switch ($engine) { before the default case.

            case 'aws-polly':
                    exec($enginebin." /opt/aws-nodejs-sample/script.js --mp3=/var/lib/asterisk/sounds/tts/$engine-tts-$hash.mp3 --text='$text' --wav=/var/lib/asterisk/sounds/tts/$engine-tts-$hash");
                    break;

3c) IMPORTANT NOTE: Any time you apply an updated configuration in the GUI it will replace all of these steps in #3 and you will have to re-enter these changes to restore the TTS engine.

  1. Go to Settings >> Text to Speech Engines, then click + Add TTS Engine

Engine Name: Custom, then type ‘aws-polly’ without quotes.
Engine Path: /usr/bin/node

  1. Create TTS from Applications >> Text to Speech using the aws-polly engine.
    DO NOT Apply Config when you create your TTS entries, it will remove all the work in Step #3 above and you will have to re-enter it again.

You now have a fully customizable AWS/Polly TTS

And a HUGE THANK YOU to jersonjunior for all his help in getting this up and running. I came across this post and was a little hesitant, but this is a GREAT solution for TTS in FreePBX.

To make things simpler, when everything is setup, make a copy of /var/lib/asterisk/agi-bin/propolys-tts.agi as /var/lib/asterisk/agi-bin/propolys-tts.bak and then you can simply replace the file when you need to Apply Config.

3 Likes

@theclevercrib I know it was not your intent but you essentially went around our spam filters. Which is violating policy and makes the system think you are a spammer. I made your first account a normal user and changed ownership on your new posts.

2 Likes

Thank you kindly, I was going to contact a sysadmin when I could reply again.

I love the concept and thank you for the huge effort. When i follow the steps I get the following:

/opt/aws-nodejs-sample/script.js: line 1: syntax error near unexpected token (' /opt/aws-nodejs-sample/script.js: line 1: var argv = require(‘optimist’).argv;’

my script.js
var argv = require(‘optimist’).argv;
const AWS = require(‘aws-sdk’)
const Fs = require(‘fs’)
var child_process = require(‘child_process’);
const Polly = new AWS.Polly({
… etc

You need to add this to line 1:
#!/usr/bin/env node

I am trying AWS polly out, but have come to a brick wall.
When I execute the script the wav file is not created.
and no obvious error message.
Is there a way to enable a debug reporting ?

Any help appreciated.

Scripts as above
extract from full log as follows

[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] pbx.c: Executing [1@ext-tts:4] AGI(“SIP/Sip_61731230612-0000008e”, “propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node”) in new stack
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: Launched AGI Script /var/lib/asterisk/agi-bin/propolys-tts.agi
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: TTS AGI Started
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: Generated WAV file: /var/lib/asterisk/sounds/tts/aws-polly-tts-df04e889735f84e9670a11fbe67d89b9.wav
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: TXT file: /var/lib/asterisk/sounds/tts/aws-polly-tts-df04e889735f84e9670a11fbe67d89b9.txt
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: Text to speech wave file doesnt exist, lets create it.
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: Executing aws-polly
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: File was not created!
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: propolys-tts.agi,“this is a test of aws Polly”,aws-polly,/usr/bin/node: TTS AGI end
[2017-10-09 14:08:25] VERBOSE[4758][C-00000092] res_agi.c: <SIP/Sip_61731230612-0000008e>AGI Script propolys-tts.agi completed, returning 0

Permissions seem ok too

Belay my last post
Word of warning for others following this thread.
When you cut and paste your AWS access keys do not lose the commas at the end of the line.
:grin:

So this is working if you can follow directions?
Can someone make this easy for the rest of us to implement?

Hello. How could we enable polly for two languages at the same time? so i tried to create 2 scripts for these languages. and i added two cases like that

    case 'aws-polly-en':
            exec($enginebin." /opt/aws-nodejs-sample/script_en.js --mp3=/var/lib/asterisk/sounds/tts/$engine-tts-$hash.mp3 --text='$text' --wav=/var/lib/asterisk/sounds/tts/$engine-tts-$hash");
            break;

    case 'aws-polly-tr':
            exec($enginebin." /opt/aws-nodejs-sample/script_tr.js --mp3=/var/lib/asterisk/sounds/tts/$engine-tts-$hash.mp3 --text='$text' --wav=/var/lib/asterisk/sounds/tts/$engine-tts-$hash");
            break;

However couldn’t add two engines to the TTS Engine. It warns me “/usr/bin/node already used, please use a different Engine Path.”

Any solution?