Added FHG(file-http-get) message playback option to download file from website to the VD_amd.agi Added example script for AWS Polly TTS generation of audio prompts Updated documentation git-svn-id: svn://192.168.202.10@3594 3d104415-ff17-0410-8863-d5cf3c621b8a
238 lines
8.0 KiB
PHP
238 lines
8.0 KiB
PHP
<?php
|
|
# vdc_AWS_polly_TTS.php
|
|
#
|
|
# Copyright (C) 2022 Matt Florell <vicidial@gmail.com> LICENSE: AGPLv2
|
|
#
|
|
# This script is designed to send a request to Amazon's AWS Polly Text-to-Speech
|
|
# service and receive back a PCM audio file(8k, 16bit, mono). Then add a WAV
|
|
# file header to it so it can be played natively in Asterisk.
|
|
#
|
|
# !!! THE AWS PHP SDK IS REQUIRED!!! You can download it here:
|
|
# http://docs.aws.amazon.com/aws-sdk-php/v3/download/aws.zip
|
|
# (the above zip file contains over 3,000 files, make sure you have space)
|
|
# (unzip it inside a new 'polly' directory in the 'agc' web directory)
|
|
#
|
|
# !!! IMPORTANT !!! You must customize this script to your needs, and you must
|
|
# populate the credentials and region for your AWS account
|
|
#
|
|
# !!! IMPORTANT !!! This script assumes that the directory exists and is writable:
|
|
# agc/polly/generated
|
|
#
|
|
### Example URL to use in a SCRIPT tab Iframe:
|
|
# http://127.0.0.1/agc/vdc_AWS_polly_TTS.php?user=--A--user--B--&pass=--A--pass--B--&counter=--A--lead_id--B--&message=message+goes+here
|
|
#
|
|
# CHANGELOG:
|
|
# 220410-2127 - First build of script
|
|
#
|
|
|
|
$version = '2.14-1';
|
|
$build = '220410-2127';
|
|
$api_script = 'AWS_polly';
|
|
|
|
$startMS = microtime();
|
|
|
|
require_once("dbconnect_mysqli.php");
|
|
require_once("functions.php");
|
|
|
|
$query_string = getenv("QUERY_STRING");
|
|
|
|
if (isset($_GET["user"])) {$user=$_GET["user"];}
|
|
elseif (isset($_POST["user"])) {$user=$_POST["user"];}
|
|
if (isset($_GET["pass"])) {$pass=$_GET["pass"];}
|
|
elseif (isset($_POST["pass"])) {$pass=$_POST["pass"];}
|
|
if (isset($_GET["message"])) {$message=$_GET["message"];}
|
|
elseif (isset($_POST["message"])) {$message=$_POST["message"];}
|
|
if (isset($_GET["counter"])) {$counter=$_GET["counter"];}
|
|
elseif (isset($_POST["counter"])) {$counter=$_POST["counter"];}
|
|
if (isset($_GET["force"])) {$force=$_GET["force"];}
|
|
elseif (isset($_POST["force"])) {$force=$_POST["force"];}
|
|
if (isset($_GET["voice"])) {$voice=$_GET["voice"];}
|
|
elseif (isset($_POST["voice"])) {$voice=$_POST["voice"];}
|
|
if (isset($_GET["DB"])) {$DB=$_GET["DB"];}
|
|
elseif (isset($_POST["DB"])) {$DB=$_POST["DB"];}
|
|
|
|
$DB=preg_replace("/[^0-9a-zA-Z]/","",$DB);
|
|
$user=preg_replace("/\'|\"|\\\\|;| /","",$user);
|
|
$pass=preg_replace("/\'|\"|\\\\|;| /","",$pass);
|
|
|
|
#############################################
|
|
##### START SYSTEM_SETTINGS LOOKUP #####
|
|
$stmt = "SELECT use_non_latin,allow_sipsak_messages,enable_languages,language_method,meetme_enter_login_filename,meetme_enter_leave3way_filename,agent_debug_logging,allow_web_debug FROM system_settings;";
|
|
$rslt=mysql_to_mysqli($stmt, $link);
|
|
#if ($DB) {echo "$stmt\n";}
|
|
$qm_conf_ct = mysqli_num_rows($rslt);
|
|
if ($qm_conf_ct > 0)
|
|
{
|
|
$row=mysqli_fetch_row($rslt);
|
|
$non_latin = $row[0];
|
|
$allow_sipsak_messages = $row[1];
|
|
$SSenable_languages = $row[2];
|
|
$SSlanguage_method = $row[3];
|
|
$meetme_enter_login_filename = $row[4];
|
|
$meetme_enter_leave3way_filename = $row[5];
|
|
$SSagent_debug_logging = $row[6];
|
|
$SSallow_web_debug = $row[7];
|
|
}
|
|
if ($SSallow_web_debug < 1) {$DB=0;}
|
|
##### END SETTINGS LOOKUP #####
|
|
###########################################
|
|
|
|
header ("Content-type: text/html; charset=utf-8");
|
|
header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
|
|
header ("Pragma: no-cache"); // HTTP/1.0
|
|
|
|
$txt = '.txt';
|
|
$StarTtime = date("U");
|
|
$NOW_DATE = date("Y-m-d");
|
|
$NOW_TIME = date("Y-m-d H:i:s");
|
|
$CIDdate = date("mdHis");
|
|
$ENTRYdate = date("YmdHis");
|
|
$MT[0]='';
|
|
|
|
$message = preg_replace("/\'|\\\\|;/","",$message);
|
|
$counter = preg_replace("/[^0-9]/","",$counter);
|
|
$force = preg_replace("/[^0-9]/","",$force);
|
|
$voice = preg_replace("/[^-_0-9a-zA-Z]/","",$voice);
|
|
|
|
if ($non_latin < 1)
|
|
{
|
|
$user=preg_replace("/[^-_0-9a-zA-Z]/","",$user);
|
|
$pass=preg_replace("/[^-_0-9a-zA-Z]/","",$pass);
|
|
}
|
|
else
|
|
{
|
|
$user = preg_replace('/[^-_0-9\p{L}]/u','',$user);
|
|
$pass = preg_replace('/[^-\.\+\/\=_0-9\p{L}]/u','',$pass);
|
|
}
|
|
|
|
# check user auth
|
|
$auth=0;
|
|
$auth_message = user_authorization($user,$pass,'',0,0,0,0,'AWS_polly');
|
|
if ($auth_message == 'GOOD')
|
|
{$auth=1;}
|
|
|
|
if ( (strlen($user)<2) or (strlen($pass)<2) or ($auth==0) )
|
|
{
|
|
echo _QXZ("Invalid Username/Password:")." |$user|$pass|$auth|$authlive|$auth_message|\n";
|
|
exit;
|
|
}
|
|
|
|
|
|
if (strlen($message) < 1)
|
|
{
|
|
echo "ERROR: invalid message: |$message|\n";
|
|
}
|
|
else
|
|
{
|
|
if (strlen($message) < 10)
|
|
{$message = '<speak>this is a test of the AWS Polly text to speech service. Number test, <say-as interpret-as="characters">1234567890</say-as>. Currency test, 987654321 dollars and 98 cents. Done.</speak>';}
|
|
if (strlen($voice) < 1) {$voice = 'Matthew';}
|
|
|
|
require_once './polly/aws-autoloader.php';
|
|
|
|
$awsAccessKeyId = 'XXXXXXXXXXXXXXXXXXXX';
|
|
$awsSecretKey = 'YYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYYY';
|
|
$credentials = new \Aws\Credentials\Credentials($awsAccessKeyId, $awsSecretKey);
|
|
$client = new \Aws\Polly\PollyClient([
|
|
'version' => '2016-06-10',
|
|
'credentials' => $credentials,
|
|
'region' => 'us-east-1',
|
|
]);
|
|
$result = $client->synthesizeSpeech([
|
|
'Engine' => 'neural',
|
|
'OutputFormat' => 'pcm',
|
|
'SampleRate' => '8000',
|
|
'Text' => $message,
|
|
'TextType' => 'ssml',
|
|
'VoiceId' => $voice,
|
|
]);
|
|
|
|
$resultData = $result->get('AudioStream')->getContents();
|
|
|
|
# $resultData = file_get_contents('polly.raw');
|
|
//Output file
|
|
$temp_filename = "./polly/generated/".$counter."_TTS.wav";
|
|
$fp = fopen($temp_filename, 'wb');
|
|
|
|
$pcm_size = strlen($resultData);
|
|
$size = 36 + $pcm_size;
|
|
$chunk_size = 16;
|
|
$audio_format = 1;
|
|
$channels = 1; //mono
|
|
$sample_rate = 8000; //Hz #From the AWS Polly documentation: Valid values for pcm are "8000" and "16000" The default value is "16000".
|
|
$bits_per_sample = 16;
|
|
$block_align = $channels * $bits_per_sample / 8;
|
|
$byte_rate = $sample_rate * $channels * $bits_per_sample / 8;
|
|
|
|
//RIFF chunk descriptor
|
|
fwrite($fp, 'RIFF');
|
|
fwrite($fp,pack('I', $size));
|
|
fwrite($fp, 'WAVE');
|
|
//fmt sub-chunk
|
|
fwrite($fp, 'fmt ');
|
|
fwrite($fp,pack('I', $chunk_size));
|
|
fwrite($fp,pack('v', $audio_format));
|
|
fwrite($fp,pack('v', $channels));
|
|
fwrite($fp,pack('I', $sample_rate));
|
|
fwrite($fp,pack('I', $byte_rate));
|
|
fwrite($fp,pack('v', $block_align));
|
|
fwrite($fp,pack('v', $bits_per_sample));
|
|
//data sub-chunk
|
|
fwrite($fp, 'data');
|
|
fwrite($fp,pack('i', $pcm_size));
|
|
fwrite($fp, $resultData);
|
|
|
|
fclose($fp);
|
|
|
|
|
|
$endMS = microtime();
|
|
$startMSary = explode(" ",$startMS);
|
|
$endMSary = explode(" ",$endMS);
|
|
$runS = ($endMSary[0] - $startMSary[0]);
|
|
$runM = ($endMSary[1] - $startMSary[1]);
|
|
$TOTALrun = ($runS + $runM);
|
|
|
|
echo "SUCCESS|".$counter."_TTS.wav|\n";
|
|
|
|
# Log request to vicidial_api_log
|
|
$stmt="INSERT INTO vicidial_api_log set user='polly',agent_user='$user',function='aws_polly',value='TTS',result=\"GOOD\",result_reason='$counter ".$counter."_TTS.wav bytes: $size voice: $voice',source='AWS',data='$message',api_date=NOW(),api_script='$api_script',run_time='$TOTALrun',webserver='',api_url='';";
|
|
$rslt=mysql_to_mysqli($stmt, $link);
|
|
$ALaffected_rows = mysqli_affected_rows($link);
|
|
if ($DB > 0) {echo "LOG: $ALaffected_rows|$stmt|\n";}
|
|
|
|
|
|
|
|
# example export of mp3 audio data
|
|
# header('Content-Transfer-Encoding: binary');
|
|
# header('Content-Type: audio/wave, audio/wav, audio/x-wav, audio/x-pn-wav');
|
|
# header('Content-Type: audio/mpeg, audio/x-mpeg, audio/x-mpeg-3, audio/mpeg3');
|
|
# header('Content-length: ' . strlen($resultData));
|
|
# header('Content-Disposition: attachment; filename="pollyTTS.wav"');
|
|
# header('X-Pad: avoid browser bug');
|
|
# header('Cache-Control: no-cache');
|
|
# echo $resultData;
|
|
|
|
# output as MP3 to listen
|
|
# $size = strlen($resultData); // File size
|
|
# $length = $size; // Content length
|
|
# $start = 0; // Start byte
|
|
# $end = $size - 1; // End byte
|
|
# header('Content-Transfer-Encoding:chunked');
|
|
# header("Content-Type: audio/mpeg");
|
|
# header("Accept-Ranges: 0-$length");
|
|
# header("Content-Range: bytes $start-$end/$size");
|
|
# header("Content-Length: $length");
|
|
# echo $resultData;
|
|
|
|
# output as MP3 to download
|
|
# header('Content-length: ' . strlen($resultData));
|
|
# header('Content-Disposition: attachment; filename="polly-text-to-speech.mp3"');
|
|
# header('X-Pad: avoid browser bug');
|
|
# header('Cache-Control: no-cache');
|
|
# echo $resultData;
|
|
}
|
|
|
|
exit;
|
|
|
|
?>
|