node-red-contrib-sonospollytts
Advanced tools
Comparing version 1.1.31 to 1.1.32
@@ -6,3 +6,9 @@ ![Sample Node](img/logo.png) | ||
<p> | ||
<b>Version 1.1.31</b> September 2020<br/> | ||
<b>Version 1.1.32</b> October 2020<br/> | ||
- Optimized the code to better handling HTTP calls for UI list.<br/> | ||
- NEW: from now, the avaiable voice list is downloaded directly from AWS Polly website. Non more "forgotten" voices.<br/> | ||
- Reordering of voices by language, to better find your preferred one.<br/> | ||
</p> | ||
<p> | ||
<b>Version 1.1.31</b> October 2020<br/> | ||
- FIX: fixed possible issue in saving/retrieving own audio files and own audio hailings, for node-red running in non standard way, like docker, home assistant plugin etc...<br/> | ||
@@ -9,0 +15,0 @@ </p> |
{ | ||
"name": "node-red-contrib-sonospollytts", | ||
"version": "1.1.31", | ||
"version": "1.1.32", | ||
"description": "Node-Red TTS with Sonos and Amazon Polly or with your own local mp3 announcement files. Transforms the text in speech and hear it using Sonos player. Can work OFFLINE as well! This node is specific for security alarm announcement, doorbell, weather annoucement etc.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
@@ -7,2 +7,4 @@ module.exports = function (RED) { | ||
var path = require("path"); | ||
var formidable = require('formidable'); | ||
const oOS = require('os'); | ||
@@ -24,5 +26,174 @@ AWS.config.update({ | ||
node.polly = new AWS.Polly(params); | ||
node.userDir = path.join(RED.settings.userDir, "sonospollyttsstorage"); // 09/03/2020 Storage of sonospollytts (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files) | ||
// 26/10/2020 Check for path and create it if doens't exists | ||
function setupDirectory(_aPath) { | ||
if (!fs.existsSync(_aPath)) { | ||
// Create the path | ||
try { | ||
fs.mkdirSync(_aPath); | ||
return true; | ||
} catch (error) { return false; } | ||
} else { | ||
return true; | ||
} | ||
} | ||
// 03/06/2019 you can select the temp dir | ||
if (!setupDirectory(node.userDir)) { | ||
RED.log.error('SonosPollyTTS: Unable to set up MAIN directory: ' + node.userDir); | ||
} | ||
if (!setupDirectory(path.join(node.userDir, "ttsfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up cache directory: ' + path.join(node.userDir, "ttsfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: TTS cache set to ' + path.join(node.userDir, "ttsfiles")); | ||
} | ||
if (!setupDirectory(path.join(node.userDir, "hailingpermanentfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up hailing directory: ' + path.join(node.userDir, "hailingpermanentfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: hailing path set to ' + path.join(node.userDir, "hailingpermanentfiles")); | ||
// 09/03/2020 Copy defaults to the userDir | ||
fs.readdirSync(path.join(__dirname, "hailingpermanentfiles")).forEach(file => { | ||
try { | ||
fs.copyFileSync(path.join(__dirname, "hailingpermanentfiles", file), path.join(node.userDir, "hailingpermanentfiles", file)); | ||
} catch (error) { } | ||
}); | ||
} | ||
if (!setupDirectory(path.join(node.userDir, "ttspermanentfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up permanent files directory: ' + path.join(node.userDir, "ttspermanentfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: permanent files path set to ' + path.join(node.userDir, "ttspermanentfiles")); | ||
// 09/03/2020 // Copy the samples of permanent files into the userDir | ||
fs.readdirSync(path.join(__dirname, "ttspermanentfiles")).forEach(file => { | ||
try { | ||
fs.copyFileSync(path.join(__dirname, "ttspermanentfiles", file), path.join(node.userDir, "ttspermanentfiles", file)); | ||
} catch (error) { } | ||
}); | ||
} | ||
// 21/03/2019 Endpoint for retrieving the default IP | ||
RED.httpAdmin.get("/sonospollyTTSGetEthAddress", RED.auth.needsPermission('PollyConfigNode.read'), function (req, res) { | ||
var oiFaces = oOS.networkInterfaces(); | ||
var jListInterfaces = []; | ||
try { | ||
Object.keys(oiFaces).forEach(ifname => { | ||
// Interface with single IP | ||
if (Object.keys(oiFaces[ifname]).length === 1) { | ||
if (Object.keys(oiFaces[ifname])[0].internal == false) jListInterfaces.push({ name: ifname, address: Object.keys(oiFaces[ifname])[0].address }); | ||
} else { | ||
var sAddresses = ""; | ||
oiFaces[ifname].forEach(function (iface) { | ||
if (iface.internal == false && iface.family === "IPv4") sAddresses = iface.address; | ||
}); | ||
if (sAddresses !== "") jListInterfaces.push({ name: ifname, address: sAddresses }); | ||
} | ||
}) | ||
} catch (error) { } | ||
if (jListInterfaces.length > 0) { | ||
res.json(jListInterfaces[0].address); // Retunr the first usable IP | ||
} else { | ||
res.json("NO ETH INTERFACE FOUND"); | ||
} | ||
}); | ||
// 20/03/2020 in the middle of coronavirus, get the sonos groups | ||
RED.httpAdmin.get("/sonosgetAllGroups", RED.auth.needsPermission('PollyConfigNode.read'), function (req, res) { | ||
var jListGroups = []; | ||
try { | ||
const discovery = new sonos.AsyncDeviceDiscovery() | ||
discovery.discover().then((device, model) => { | ||
return device.getAllGroups().then((groups) => { | ||
//RED.log.warn('Groups ' + JSON.stringify(groups, null, 2)) | ||
for (let index = 0; index < groups.length; index++) { | ||
const element = groups[index]; | ||
jListGroups.push({ name: element.Name, host: element.host }) | ||
} | ||
res.json(jListGroups) | ||
//return groups[0].CoordinatorDevice().togglePlayback() | ||
}) | ||
}).catch(e => { | ||
RED.log.warn('SonosPollyTTS: Error in discovery ' + e); | ||
res.json("ERRORDISCOVERY"); | ||
}) | ||
} catch (error) { } | ||
}); | ||
// 09/03/2020 Get list of filenames in hailing folder | ||
RED.httpAdmin.get("/getHailingFilesList", RED.auth.needsPermission('PollyConfigNode.read'), function (req, res) { | ||
var jListOwnFiles = []; | ||
var sName = ""; | ||
try { | ||
fs.readdirSync(path.join(node.userDir, "hailingpermanentfiles")).forEach(file => { | ||
if (file.indexOf("Hailing_") > -1) { | ||
sName = file.replace("Hailing_", "").replace(".mp3", ""); | ||
jListOwnFiles.push({ name: sName, filename: file }); | ||
} | ||
}); | ||
} catch (error) { } | ||
res.json(jListOwnFiles) | ||
}); | ||
// 09/03/2020 Delete Hailing | ||
RED.httpAdmin.get("/deleteHailingFile", RED.auth.needsPermission('PollyConfigNode.read'), function (req, res) { | ||
// Delete the file | ||
try { | ||
var newPath = path.join(node.userDir, "hailingpermanentfiles", req.query.FileName); | ||
fs.unlinkSync(newPath) | ||
} catch (error) { } | ||
res.json({ status: 220 }); | ||
}); | ||
// 09/03/2020 Receive new hailing files from html | ||
RED.httpAdmin.post("/node-red-contrib-sonospollyttsHailing", function (req, res) { | ||
var form = new formidable.IncomingForm(); | ||
form.parse(req, function (err, fields, files) { | ||
if (err) { }; | ||
// Allow only mp3 | ||
if (files.customHailing.name.indexOf(".mp3") !== -1) { | ||
var newPath = path.join(node.userDir, "hailingpermanentfiles", "Hailing_" + files.customHailing.name); | ||
fs.rename(files.customHailing.path, newPath, function (err) { }); | ||
} | ||
}); | ||
res.json({ status: 220 }); | ||
res.end; | ||
}); | ||
// 26/10/2020 Supergiovane, get the real updated voice list. | ||
RED.httpAdmin.get("/pollygetvoices", RED.auth.needsPermission('PollyConfigNode.read'), function (req, res) { | ||
var jListVoices = []; | ||
try { | ||
// https://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/Polly.html#describeVoices-property | ||
var jfiltroVoci = { | ||
//Engine: standard | neural, | ||
//IncludeAdditionalLanguageCodes: true | ||
//LanguageCode: arb | cmn-CN | cy-GB | da-DK | de-DE | en-AU | en-GB | en-GB-WLS | en-IN | en-US | es-ES | es-MX | es-US | fr-CA | fr-FR | is-IS | it-IT | ja-JP | hi-IN | ko-KR | nb-NO | nl-NL | pl-PL | pt-BR | pt-PT | ro-RO | ru-RU | sv-SE | tr-TR, | ||
//NextToken: "STRING_VALUE" | ||
}; | ||
node.polly.describeVoices(jfiltroVoci, function (err, data) { | ||
if (err) { | ||
RED.log.warn('SonosPollyTTS: Error getting polly voices ' + err); | ||
} else { | ||
for (let index = 0; index < data.Voices.length; index++) { | ||
const oVoice = data.Voices[index]; | ||
jListVoices.push({ name: oVoice.LanguageName + " (" + oVoice.LanguageCode + ") " + oVoice.Name + " - " + oVoice.Gender, id: oVoice.Id }) | ||
} | ||
res.json(jListVoices) | ||
} | ||
}); | ||
} catch (error) { } | ||
}); | ||
node.oWebserver; // 11/11/2019 Stores the Webserver | ||
node.purgediratrestart = config.purgediratrestart || "leave"; // 26/02/2020 | ||
node.userDir = path.join(RED.settings.userDir , "sonospollyttsstorage"); // 09/03/2020 Storage of sonospollytts (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files) | ||
node.userDir = path.join(RED.settings.userDir, "sonospollyttsstorage"); // 09/03/2020 Storage of sonospollytts (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files) | ||
node.noderedport = typeof config.noderedport === "undefined" ? "1980" : config.noderedport; | ||
@@ -41,24 +212,24 @@ // 11/11/2019 NEW in V 1.1.0, changed webserver behaviour. Redirect pre V. 1.1.0 1880 ports to the nde default 1980 | ||
try { | ||
fs.readdirSync(path.join(node.userDir , "ttsfiles"), (err, files) => { | ||
fs.readdirSync(path.join(node.userDir, "ttsfiles"), (err, files) => { | ||
try { | ||
if (files.length > 0) { | ||
files.forEach(function (file) { | ||
RED.log.info("SonospollyTTS-config: Deleted TTS file " + path.join(node.userDir , "ttsfiles" , file)); | ||
RED.log.info("SonospollyTTS-config: Deleted TTS file " + path.join(node.userDir, "ttsfiles", file)); | ||
try { | ||
fs.unlink(path.join(node.userDir , "ttsfiles" , file)), err => { }; | ||
fs.unlink(path.join(node.userDir, "ttsfiles", file)), err => { }; | ||
} catch (error) { | ||
} | ||
}); | ||
}; | ||
}; | ||
} catch (error) { | ||
} | ||
}); | ||
} catch (error) { } | ||
}; | ||
// 11/11/2019 CREATE THE ENDPOINT | ||
@@ -65,0 +236,0 @@ // ################################# |
@@ -10,4 +10,3 @@ module.exports = function (RED) { | ||
const sonos = require('sonos'); | ||
var formidable = require('formidable'); | ||
const oOS = require('os'); | ||
@@ -52,517 +51,5 @@ AWS.config.update({ | ||
// 26/10/2020 Check for path and create it if doens't exists | ||
function setupDirectory(_aPath) { | ||
if (!fs.existsSync(_aPath)) { | ||
// Create the path | ||
try { | ||
fs.mkdirSync(_aPath); | ||
return true; | ||
} catch (error) { return false; } | ||
} else { | ||
return true; | ||
} | ||
} | ||
var voices = { | ||
'0': { | ||
Gender: 'Female', | ||
Id: 'Joanna', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joanna', | ||
Engine: 'standard' | ||
}, | ||
'1': { | ||
Gender: 'Female', | ||
Id: 'Mizuki', | ||
LanguageCode: 'ja-JP', | ||
LanguageName: 'Japanese', | ||
Name: 'Mizuki', | ||
Engine: 'standard' | ||
}, | ||
'2': { | ||
Gender: 'Female', | ||
Id: 'Filiz', | ||
LanguageCode: 'tr-TR', | ||
LanguageName: 'Turkish', | ||
Name: 'Filiz', | ||
Engine: 'standard' | ||
}, | ||
'3': { | ||
Gender: 'Female', | ||
Id: 'Astrid', | ||
LanguageCode: 'sv-SE', | ||
LanguageName: 'Swedish', | ||
Name: 'Astrid', | ||
Engine: 'standard' | ||
}, | ||
'4': { | ||
Gender: 'Male', | ||
Id: 'Maxim', | ||
LanguageCode: 'ru-RU', | ||
LanguageName: 'Russian', | ||
Name: 'Maxim', | ||
Engine: 'standard' | ||
}, | ||
'5': { | ||
Gender: 'Female', | ||
Id: 'Tatyana', | ||
LanguageCode: 'ru-RU', | ||
LanguageName: 'Russian', | ||
Name: 'Tatyana', | ||
Engine: 'standard' | ||
}, | ||
'6': { | ||
Gender: 'Female', | ||
Id: 'Carmen', | ||
LanguageCode: 'ro-RO', | ||
LanguageName: 'Romanian', | ||
Name: 'Carmen', | ||
Engine: 'standard' | ||
}, | ||
'7': { | ||
Gender: 'Female', | ||
Id: 'Ines', | ||
LanguageCode: 'pt-PT', | ||
LanguageName: 'Portuguese', | ||
Name: 'Inês', | ||
Engine: 'standard' | ||
}, | ||
'8': { | ||
Gender: 'Male', | ||
Id: 'Cristiano', | ||
LanguageCode: 'pt-PT', | ||
LanguageName: 'Portuguese', | ||
Name: 'Cristiano', | ||
Engine: 'standard' | ||
}, | ||
'9': { | ||
Gender: 'Female', | ||
Id: 'Vitoria', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Vitória', | ||
Engine: 'standard' | ||
}, | ||
'10': { | ||
Gender: 'Male', | ||
Id: 'Ricardo', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Ricardo', | ||
Engine: 'standard' | ||
}, | ||
'11': { | ||
Gender: 'Female', | ||
Id: 'Maja', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Maja', | ||
Engine: 'standard' | ||
}, | ||
'12': { | ||
Gender: 'Male', | ||
Id: 'Jan', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Jan', | ||
Engine: 'standard' | ||
}, | ||
'13': { | ||
Gender: 'Female', | ||
Id: 'Ewa', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Ewa', | ||
Engine: 'standard' | ||
}, | ||
'14': { | ||
Gender: 'Male', | ||
Id: 'Ruben', | ||
LanguageCode: 'nl-NL', | ||
LanguageName: 'Dutch', | ||
Name: 'Ruben', | ||
Engine: 'standard' | ||
}, | ||
'15': { | ||
Gender: 'Female', | ||
Id: 'Lotte', | ||
LanguageCode: 'nl-NL', | ||
LanguageName: 'Dutch', | ||
Name: 'Lotte', | ||
Engine: 'standard' | ||
}, | ||
'16': { | ||
Gender: 'Female', | ||
Id: 'Liv', | ||
LanguageCode: 'nb-NO', | ||
LanguageName: 'Norwegian', | ||
Name: 'Liv', | ||
Engine: 'standard' | ||
}, | ||
'17': { | ||
Gender: 'Male', | ||
Id: 'Giorgio', | ||
LanguageCode: 'it-IT', | ||
LanguageName: 'Italian', | ||
Name: 'Giorgio', | ||
Engine: 'standard' | ||
}, | ||
'18': { | ||
Gender: 'Female', | ||
Id: 'Carla', | ||
LanguageCode: 'it-IT', | ||
LanguageName: 'Italian', | ||
Name: 'Carla', | ||
Engine: 'standard' | ||
}, | ||
'19': { | ||
Gender: 'Male', | ||
Id: 'Karl', | ||
LanguageCode: 'is-IS', | ||
LanguageName: 'Icelandic', | ||
Name: 'Karl', | ||
Engine: 'standard' | ||
}, | ||
'20': { | ||
Gender: 'Female', | ||
Id: 'Dora', | ||
LanguageCode: 'is-IS', | ||
LanguageName: 'Icelandic', | ||
Name: 'Dóra', | ||
Engine: 'standard' | ||
}, | ||
'21': { | ||
Gender: 'Male', | ||
Id: 'Mathieu', | ||
LanguageCode: 'fr-FR', | ||
LanguageName: 'French', | ||
Name: 'Mathieu', | ||
Engine: 'standard' | ||
}, | ||
'22': { | ||
Gender: 'Female', | ||
Id: 'Celine', | ||
LanguageCode: 'fr-FR', | ||
LanguageName: 'French', | ||
Name: 'Céline', | ||
Engine: 'standard' | ||
}, | ||
'23': { | ||
Gender: 'Female', | ||
Id: 'Chantal', | ||
LanguageCode: 'fr-CA', | ||
LanguageName: 'Canadian French', | ||
Name: 'Chantal', | ||
Engine: 'standard' | ||
}, | ||
'24': { | ||
Gender: 'Female', | ||
Id: 'Penelope', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Penélope', | ||
Engine: 'standard' | ||
}, | ||
'25': { | ||
Gender: 'Male', | ||
Id: 'Miguel', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Miguel', | ||
Engine: 'standard' | ||
}, | ||
'26': { | ||
Gender: 'Male', | ||
Id: 'Enrique', | ||
LanguageCode: 'es-ES', | ||
LanguageName: 'Castilian Spanish', | ||
Name: 'Enrique', | ||
Engine: 'standard' | ||
}, | ||
'27': { | ||
Gender: 'Female', | ||
Id: 'Conchita', | ||
LanguageCode: 'es-ES', | ||
LanguageName: 'Castilian Spanish', | ||
Name: 'Conchita', | ||
Engine: 'standard' | ||
}, | ||
'28': { | ||
Gender: 'Male', | ||
Id: 'Geraint', | ||
LanguageCode: 'en-GB-WLS', | ||
LanguageName: 'Welsh English', | ||
Name: 'Geraint', | ||
Engine: 'standard' | ||
}, | ||
'29': { | ||
Gender: 'Female', | ||
Id: 'Salli', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Salli', | ||
Engine: 'standard' | ||
}, | ||
'30': { | ||
Gender: 'Female', | ||
Id: 'Kimberly', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kimberly', | ||
Engine: 'standard' | ||
}, | ||
'31': { | ||
Gender: 'Female', | ||
Id: 'Kendra', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kendra', | ||
Engine: 'standard' | ||
}, | ||
'32': { | ||
Gender: 'Male', | ||
Id: 'Justin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Justin', | ||
Engine: 'standard' | ||
}, | ||
'33': { | ||
Gender: 'Male', | ||
Id: 'Joey', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joey', | ||
Engine: 'standard' | ||
}, | ||
'34': { | ||
Gender: 'Female', | ||
Id: 'Ivy', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Ivy', | ||
Engine: 'standard' | ||
}, | ||
'35': { | ||
Gender: 'Female', | ||
Id: 'Raveena', | ||
LanguageCode: 'en-IN', | ||
LanguageName: 'Indian English', | ||
Name: 'Raveena', | ||
Engine: 'standard' | ||
}, | ||
'36': { | ||
Gender: 'Female', | ||
Id: 'Emma', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Emma', | ||
Engine: 'standard' | ||
}, | ||
'37': { | ||
Gender: 'Male', | ||
Id: 'Brian', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Brian', | ||
Engine: 'standard' | ||
}, | ||
'38': { | ||
Gender: 'Female', | ||
Id: 'Amy', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Amy', | ||
Engine: 'standard' | ||
}, | ||
'39': { | ||
Gender: 'Male', | ||
Id: 'Russell', | ||
LanguageCode: 'en-AU', | ||
LanguageName: 'Australian English', | ||
Name: 'Russell', | ||
Engine: 'standard' | ||
}, | ||
'40': { | ||
Gender: 'Female', | ||
Id: 'Nicole', | ||
LanguageCode: 'en-AU', | ||
LanguageName: 'Australian English', | ||
Name: 'Nicole', | ||
Engine: 'standard' | ||
}, | ||
'41': { | ||
Gender: 'Female', | ||
Id: 'Marlene', | ||
LanguageCode: 'de-DE', | ||
LanguageName: 'German', | ||
Name: 'Marlene', | ||
Engine: 'standard' | ||
}, | ||
'42': { | ||
Gender: 'Male', | ||
Id: 'Hans', | ||
LanguageCode: 'de-DE', | ||
LanguageName: 'German', | ||
Name: 'Hans', | ||
Engine: 'standard' | ||
}, | ||
'43': { | ||
Gender: 'Female', | ||
Id: 'Naja', | ||
LanguageCode: 'da-DK', | ||
LanguageName: 'Danish', | ||
Name: 'Naja', | ||
Engine: 'standard' | ||
}, | ||
'44': { | ||
Gender: 'Male', | ||
Id: 'Mads', | ||
LanguageCode: 'da-DK', | ||
LanguageName: 'Danish', | ||
Name: 'Mads', | ||
Engine: 'standard' | ||
}, | ||
'45': { | ||
Gender: 'Female', | ||
Id: 'Gwyneth', | ||
LanguageCode: 'cy-GB', | ||
LanguageName: 'Welsh', | ||
Name: 'Gwyneth', | ||
Engine: 'standard' | ||
}, | ||
'46': { | ||
Gender: 'Male', | ||
Id: 'Jacek', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Jacek', | ||
Engine: 'standard' | ||
}, | ||
'47': { | ||
Gender: 'Male', | ||
Id: 'Matthew', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Matthew', | ||
Engine: 'standard' | ||
}, | ||
'48': { | ||
Gender: 'Male', | ||
Id: 'Matthew', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Matthew (neural)', | ||
Engine: 'neural' | ||
}, | ||
'49': { | ||
Gender: 'Female', | ||
Id: 'Amy', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Amy (neural)', | ||
Engine: 'neural' | ||
}, | ||
'50': { | ||
Gender: 'Female', | ||
Id: 'Emma', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Emma (neural)', | ||
Engine: 'neural' | ||
}, | ||
'51': { | ||
Gender: 'Male', | ||
Id: 'Brian', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Brian (neural)', | ||
Engine: 'neural' | ||
}, | ||
'52': { | ||
Gender: 'Female', | ||
Id: 'Ivy', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Ivy (neural)', | ||
Engine: 'neural' | ||
}, | ||
'53': { | ||
Gender: 'Female', | ||
Id: 'Joanna', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joanna (neural)', | ||
Engine: 'neural' | ||
}, | ||
'54': { | ||
Gender: 'Female', | ||
Id: 'Kendra', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kendra (neural)', | ||
Engine: 'neural' | ||
}, | ||
'55': { | ||
Gender: 'Female', | ||
Id: 'Kimberly', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kimberly (neural)', | ||
Engine: 'neural' | ||
}, | ||
'56': { | ||
Gender: 'Female', | ||
Id: 'Salli', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Salli (neural)', | ||
Engine: 'neural' | ||
}, | ||
'57': { | ||
Gender: 'Male', | ||
Id: 'Joey', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joey (neural)', | ||
Engine: 'neural' | ||
}, | ||
'58': { | ||
Gender: 'Male', | ||
Id: 'Justin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Justin (neural)', | ||
Engine: 'neural' | ||
}, | ||
'59': { | ||
Gender: 'Male', | ||
Id: 'Kevin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kevin (neural)', | ||
Engine: 'neural' | ||
}, | ||
'60': { | ||
Gender: 'Female', | ||
Id: 'Camila', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Camila (neural)', | ||
Engine: 'neural' | ||
}, | ||
'61': { | ||
Gender: 'Female', | ||
Id: 'Lupe', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Lupe (neural)', | ||
Engine: 'neural' | ||
} | ||
}; | ||
// Node Register | ||
@@ -577,3 +64,3 @@ function PollyNode(config) { | ||
node.SonosClient; | ||
node.iVoice; | ||
node.voiceId; | ||
node.oTimer; | ||
@@ -590,3 +77,3 @@ node.oTimerSonosConnectionCheck; | ||
node.msg.connectionerror = true; | ||
node.userDir = path.join(RED.settings.userDir , "sonospollyttsstorage"); // 09/03/2020 Storage of sonospollytts (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files) | ||
node.userDir = path.join(RED.settings.userDir, "sonospollyttsstorage"); // 09/03/2020 Storage of sonospollytts (otherwise, at each upgrade to a newer version, the node path is wiped out and recreated, loosing all custom files) | ||
node.oAdditionalSonosPlayers = []; // 20/03/2020 Contains other players to be grouped | ||
@@ -599,92 +86,2 @@ node.rules = config.rules || [{}]; | ||
// 21/03/2019 Endpoint for retrieving the default IP | ||
RED.httpAdmin.get("/sonospollyTTSGetEthAddress", RED.auth.needsPermission('PollyNode.read'), function (req, res) { | ||
var oiFaces = oOS.networkInterfaces(); | ||
var jListInterfaces = []; | ||
try { | ||
Object.keys(oiFaces).forEach(ifname => { | ||
// Interface with single IP | ||
if (Object.keys(oiFaces[ifname]).length === 1) { | ||
if (Object.keys(oiFaces[ifname])[0].internal == false) jListInterfaces.push({ name: ifname, address: Object.keys(oiFaces[ifname])[0].address }); | ||
} else { | ||
var sAddresses = ""; | ||
oiFaces[ifname].forEach(function (iface) { | ||
if (iface.internal == false && iface.family === "IPv4") sAddresses = iface.address; | ||
}); | ||
if (sAddresses !== "") jListInterfaces.push({ name: ifname, address: sAddresses }); | ||
} | ||
}) | ||
} catch (error) { } | ||
if (jListInterfaces.length > 0) { | ||
res.json(jListInterfaces[0].address); // Retunr the first usable IP | ||
} else { | ||
res.json("NO ETH INTERFACE FOUND"); | ||
} | ||
}); | ||
// 20/03/2020 in the middle of coronavirus, get the sonos groups | ||
RED.httpAdmin.get("/sonosgetAllGroups", RED.auth.needsPermission('PollyNode.read'), function (req, res) { | ||
var jListGroups = []; | ||
try { | ||
const discovery = new sonos.AsyncDeviceDiscovery() | ||
discovery.discover().then((device, model) => { | ||
return device.getAllGroups().then((groups) => { | ||
//RED.log.warn('Groups ' + JSON.stringify(groups, null, 2)) | ||
for (let index = 0; index < groups.length; index++) { | ||
const element = groups[index]; | ||
jListGroups.push({ name: element.Name, host: element.host }) | ||
} | ||
res.json(jListGroups) | ||
//return groups[0].CoordinatorDevice().togglePlayback() | ||
}) | ||
}).catch(e => { | ||
RED.log.warn('SonosPollyTTS: Error in discovery ' + e); | ||
res.json("ERRORDISCOVERY"); | ||
}) | ||
} catch (error) { } | ||
}); | ||
// 09/03/2020 Get list of filenames in hailing folder | ||
RED.httpAdmin.get("/getHailingFilesList", RED.auth.needsPermission('PollyNode.read'), function (req, res) { | ||
var jListOwnFiles = []; | ||
var sName = ""; | ||
try { | ||
fs.readdirSync(path.join(node.userDir , "hailingpermanentfiles")).forEach(file => { | ||
if (file.indexOf("Hailing_") > -1) { | ||
sName = file.replace("Hailing_", "").replace(".mp3", ""); | ||
jListOwnFiles.push({ name: sName, filename: file }); | ||
} | ||
}); | ||
} catch (error) { } | ||
res.json(jListOwnFiles) | ||
}); | ||
// 09/03/2020 Delete Hailing | ||
RED.httpAdmin.get("/deleteHailingFile", RED.auth.needsPermission('PollyNode.read'), function (req, res) { | ||
// Delete the file | ||
try { | ||
var newPath = path.join(node.userDir , "hailingpermanentfiles" , req.query.FileName); | ||
fs.unlinkSync(newPath) | ||
} catch (error) { } | ||
res.json({ status: 220 }); | ||
}); | ||
// 09/03/2020 Receive new hailing files from html | ||
RED.httpAdmin.post("/node-red-contrib-sonospollyttsHailing", function (req, res) { | ||
var form = new formidable.IncomingForm(); | ||
form.parse(req, function (err, fields, files) { | ||
if (err) { }; | ||
// Allow only mp3 | ||
if (files.customHailing.name.indexOf(".mp3") !== -1) { | ||
var newPath = path.join(node.userDir , "hailingpermanentfiles" , "Hailing_" + files.customHailing.name); | ||
fs.rename(files.customHailing.path, newPath, function (err) { }); | ||
} | ||
}); | ||
res.json({ status: 220 }); | ||
res.end; | ||
}); | ||
// 20/11/2019 Used to call the status update | ||
@@ -739,35 +136,4 @@ node.setNodeStatus = ({ fill, shape, text }) => { | ||
// 03/06/2019 you can select the temp dir | ||
if (!setupDirectory(node.userDir)) { | ||
RED.log.error('SonosPollyTTS: Unable to set up MAIN directory: ' + node.userDir); | ||
} | ||
if (!setupDirectory(path.join(node.userDir , "ttsfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up cache directory: ' + path.join(node.userDir , "ttsfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: TTS cache set to ' + path.join(node.userDir , "ttsfiles")); | ||
} | ||
if (!setupDirectory(path.join(node.userDir , "hailingpermanentfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up hailing directory: ' + path.join(node.userDir , "hailingpermanentfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: hailing path set to ' + path.join(node.userDir , "hailingpermanentfiles")); | ||
// 09/03/2020 Copy defaults to the userDir | ||
fs.readdirSync(path.join(__dirname , "hailingpermanentfiles")).forEach(file => { | ||
try { | ||
fs.copyFileSync(path.join(__dirname , "hailingpermanentfiles" , file), path.join(node.userDir , "hailingpermanentfiles" , file)); | ||
} catch (error) { } | ||
}); | ||
} | ||
if (!setupDirectory(path.join(node.userDir , "ttspermanentfiles"))) { | ||
RED.log.error('SonosPollyTTS: Unable to set up permanent files directory: ' + path.join(node.userDir , "ttspermanentfiles")); | ||
} else { | ||
RED.log.info('SonosPollyTTS: permanent files path set to ' + path.join(node.userDir , "ttspermanentfiles")); | ||
// 09/03/2020 // Copy the samples of permanent files into the userDir | ||
fs.readdirSync(path.join(__dirname , "ttspermanentfiles")).forEach(file => { | ||
try { | ||
fs.copyFileSync(path.join(__dirname , "ttspermanentfiles" , file), path.join(node.userDir , "ttspermanentfiles" , file)); | ||
} catch (error) { } | ||
}); | ||
} | ||
// Set ssml | ||
@@ -785,6 +151,506 @@ node.ssml = config.ssml; | ||
// Set the voice | ||
node.iVoice = voices[config.voice].Id; | ||
// 26/10/2020 Set the voice | ||
// Backward compatibility, to remove in the future | ||
// °°°°°°°°°°°°° | ||
var voices = { | ||
'0': { | ||
Gender: 'Female', | ||
Id: 'Joanna', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joanna', | ||
Engine: 'standard' | ||
}, | ||
'1': { | ||
Gender: 'Female', | ||
Id: 'Mizuki', | ||
LanguageCode: 'ja-JP', | ||
LanguageName: 'Japanese', | ||
Name: 'Mizuki', | ||
Engine: 'standard' | ||
}, | ||
'2': { | ||
Gender: 'Female', | ||
Id: 'Filiz', | ||
LanguageCode: 'tr-TR', | ||
LanguageName: 'Turkish', | ||
Name: 'Filiz', | ||
Engine: 'standard' | ||
}, | ||
'3': { | ||
Gender: 'Female', | ||
Id: 'Astrid', | ||
LanguageCode: 'sv-SE', | ||
LanguageName: 'Swedish', | ||
Name: 'Astrid', | ||
Engine: 'standard' | ||
}, | ||
'4': { | ||
Gender: 'Male', | ||
Id: 'Maxim', | ||
LanguageCode: 'ru-RU', | ||
LanguageName: 'Russian', | ||
Name: 'Maxim', | ||
Engine: 'standard' | ||
}, | ||
'5': { | ||
Gender: 'Female', | ||
Id: 'Tatyana', | ||
LanguageCode: 'ru-RU', | ||
LanguageName: 'Russian', | ||
Name: 'Tatyana', | ||
Engine: 'standard' | ||
}, | ||
'6': { | ||
Gender: 'Female', | ||
Id: 'Carmen', | ||
LanguageCode: 'ro-RO', | ||
LanguageName: 'Romanian', | ||
Name: 'Carmen', | ||
Engine: 'standard' | ||
}, | ||
'7': { | ||
Gender: 'Female', | ||
Id: 'Ines', | ||
LanguageCode: 'pt-PT', | ||
LanguageName: 'Portuguese', | ||
Name: 'Inês', | ||
Engine: 'standard' | ||
}, | ||
'8': { | ||
Gender: 'Male', | ||
Id: 'Cristiano', | ||
LanguageCode: 'pt-PT', | ||
LanguageName: 'Portuguese', | ||
Name: 'Cristiano', | ||
Engine: 'standard' | ||
}, | ||
'9': { | ||
Gender: 'Female', | ||
Id: 'Vitoria', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Vitória', | ||
Engine: 'standard' | ||
}, | ||
'10': { | ||
Gender: 'Male', | ||
Id: 'Ricardo', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Ricardo', | ||
Engine: 'standard' | ||
}, | ||
'11': { | ||
Gender: 'Female', | ||
Id: 'Maja', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Maja', | ||
Engine: 'standard' | ||
}, | ||
'12': { | ||
Gender: 'Male', | ||
Id: 'Jan', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Jan', | ||
Engine: 'standard' | ||
}, | ||
'13': { | ||
Gender: 'Female', | ||
Id: 'Ewa', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Ewa', | ||
Engine: 'standard' | ||
}, | ||
'14': { | ||
Gender: 'Male', | ||
Id: 'Ruben', | ||
LanguageCode: 'nl-NL', | ||
LanguageName: 'Dutch', | ||
Name: 'Ruben', | ||
Engine: 'standard' | ||
}, | ||
'15': { | ||
Gender: 'Female', | ||
Id: 'Lotte', | ||
LanguageCode: 'nl-NL', | ||
LanguageName: 'Dutch', | ||
Name: 'Lotte', | ||
Engine: 'standard' | ||
}, | ||
'16': { | ||
Gender: 'Female', | ||
Id: 'Liv', | ||
LanguageCode: 'nb-NO', | ||
LanguageName: 'Norwegian', | ||
Name: 'Liv', | ||
Engine: 'standard' | ||
}, | ||
'17': { | ||
Gender: 'Male', | ||
Id: 'Giorgio', | ||
LanguageCode: 'it-IT', | ||
LanguageName: 'Italian', | ||
Name: 'Giorgio', | ||
Engine: 'standard' | ||
}, | ||
'18': { | ||
Gender: 'Female', | ||
Id: 'Carla', | ||
LanguageCode: 'it-IT', | ||
LanguageName: 'Italian', | ||
Name: 'Carla', | ||
Engine: 'standard' | ||
}, | ||
'19': { | ||
Gender: 'Male', | ||
Id: 'Karl', | ||
LanguageCode: 'is-IS', | ||
LanguageName: 'Icelandic', | ||
Name: 'Karl', | ||
Engine: 'standard' | ||
}, | ||
'20': { | ||
Gender: 'Female', | ||
Id: 'Dora', | ||
LanguageCode: 'is-IS', | ||
LanguageName: 'Icelandic', | ||
Name: 'Dóra', | ||
Engine: 'standard' | ||
}, | ||
'21': { | ||
Gender: 'Male', | ||
Id: 'Mathieu', | ||
LanguageCode: 'fr-FR', | ||
LanguageName: 'French', | ||
Name: 'Mathieu', | ||
Engine: 'standard' | ||
}, | ||
'22': { | ||
Gender: 'Female', | ||
Id: 'Celine', | ||
LanguageCode: 'fr-FR', | ||
LanguageName: 'French', | ||
Name: 'Céline', | ||
Engine: 'standard' | ||
}, | ||
'23': { | ||
Gender: 'Female', | ||
Id: 'Chantal', | ||
LanguageCode: 'fr-CA', | ||
LanguageName: 'Canadian French', | ||
Name: 'Chantal', | ||
Engine: 'standard' | ||
}, | ||
'24': { | ||
Gender: 'Female', | ||
Id: 'Penelope', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Penélope', | ||
Engine: 'standard' | ||
}, | ||
'25': { | ||
Gender: 'Male', | ||
Id: 'Miguel', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Miguel', | ||
Engine: 'standard' | ||
}, | ||
'26': { | ||
Gender: 'Male', | ||
Id: 'Enrique', | ||
LanguageCode: 'es-ES', | ||
LanguageName: 'Castilian Spanish', | ||
Name: 'Enrique', | ||
Engine: 'standard' | ||
}, | ||
'27': { | ||
Gender: 'Female', | ||
Id: 'Conchita', | ||
LanguageCode: 'es-ES', | ||
LanguageName: 'Castilian Spanish', | ||
Name: 'Conchita', | ||
Engine: 'standard' | ||
}, | ||
'28': { | ||
Gender: 'Male', | ||
Id: 'Geraint', | ||
LanguageCode: 'en-GB-WLS', | ||
LanguageName: 'Welsh English', | ||
Name: 'Geraint', | ||
Engine: 'standard' | ||
}, | ||
'29': { | ||
Gender: 'Female', | ||
Id: 'Salli', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Salli', | ||
Engine: 'standard' | ||
}, | ||
'30': { | ||
Gender: 'Female', | ||
Id: 'Kimberly', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kimberly', | ||
Engine: 'standard' | ||
}, | ||
'31': { | ||
Gender: 'Female', | ||
Id: 'Kendra', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kendra', | ||
Engine: 'standard' | ||
}, | ||
'32': { | ||
Gender: 'Male', | ||
Id: 'Justin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Justin', | ||
Engine: 'standard' | ||
}, | ||
'33': { | ||
Gender: 'Male', | ||
Id: 'Joey', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joey', | ||
Engine: 'standard' | ||
}, | ||
'34': { | ||
Gender: 'Female', | ||
Id: 'Ivy', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Ivy', | ||
Engine: 'standard' | ||
}, | ||
'35': { | ||
Gender: 'Female', | ||
Id: 'Raveena', | ||
LanguageCode: 'en-IN', | ||
LanguageName: 'Indian English', | ||
Name: 'Raveena', | ||
Engine: 'standard' | ||
}, | ||
'36': { | ||
Gender: 'Female', | ||
Id: 'Emma', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Emma', | ||
Engine: 'standard' | ||
}, | ||
'37': { | ||
Gender: 'Male', | ||
Id: 'Brian', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Brian', | ||
Engine: 'standard' | ||
}, | ||
'38': { | ||
Gender: 'Female', | ||
Id: 'Amy', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Amy', | ||
Engine: 'standard' | ||
}, | ||
'39': { | ||
Gender: 'Male', | ||
Id: 'Russell', | ||
LanguageCode: 'en-AU', | ||
LanguageName: 'Australian English', | ||
Name: 'Russell', | ||
Engine: 'standard' | ||
}, | ||
'40': { | ||
Gender: 'Female', | ||
Id: 'Nicole', | ||
LanguageCode: 'en-AU', | ||
LanguageName: 'Australian English', | ||
Name: 'Nicole', | ||
Engine: 'standard' | ||
}, | ||
'41': { | ||
Gender: 'Female', | ||
Id: 'Marlene', | ||
LanguageCode: 'de-DE', | ||
LanguageName: 'German', | ||
Name: 'Marlene', | ||
Engine: 'standard' | ||
}, | ||
'42': { | ||
Gender: 'Male', | ||
Id: 'Hans', | ||
LanguageCode: 'de-DE', | ||
LanguageName: 'German', | ||
Name: 'Hans', | ||
Engine: 'standard' | ||
}, | ||
'43': { | ||
Gender: 'Female', | ||
Id: 'Naja', | ||
LanguageCode: 'da-DK', | ||
LanguageName: 'Danish', | ||
Name: 'Naja', | ||
Engine: 'standard' | ||
}, | ||
'44': { | ||
Gender: 'Male', | ||
Id: 'Mads', | ||
LanguageCode: 'da-DK', | ||
LanguageName: 'Danish', | ||
Name: 'Mads', | ||
Engine: 'standard' | ||
}, | ||
'45': { | ||
Gender: 'Female', | ||
Id: 'Gwyneth', | ||
LanguageCode: 'cy-GB', | ||
LanguageName: 'Welsh', | ||
Name: 'Gwyneth', | ||
Engine: 'standard' | ||
}, | ||
'46': { | ||
Gender: 'Male', | ||
Id: 'Jacek', | ||
LanguageCode: 'pl-PL', | ||
LanguageName: 'Polish', | ||
Name: 'Jacek', | ||
Engine: 'standard' | ||
}, | ||
'47': { | ||
Gender: 'Male', | ||
Id: 'Matthew', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Matthew', | ||
Engine: 'standard' | ||
}, | ||
'48': { | ||
Gender: 'Male', | ||
Id: 'Matthew', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Matthew (neural)', | ||
Engine: 'neural' | ||
}, | ||
'49': { | ||
Gender: 'Female', | ||
Id: 'Amy', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Amy (neural)', | ||
Engine: 'neural' | ||
}, | ||
'50': { | ||
Gender: 'Female', | ||
Id: 'Emma', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Emma (neural)', | ||
Engine: 'neural' | ||
}, | ||
'51': { | ||
Gender: 'Male', | ||
Id: 'Brian', | ||
LanguageCode: 'en-GB', | ||
LanguageName: 'British English', | ||
Name: 'Brian (neural)', | ||
Engine: 'neural' | ||
}, | ||
'52': { | ||
Gender: 'Female', | ||
Id: 'Ivy', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Ivy (neural)', | ||
Engine: 'neural' | ||
}, | ||
'53': { | ||
Gender: 'Female', | ||
Id: 'Joanna', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joanna (neural)', | ||
Engine: 'neural' | ||
}, | ||
'54': { | ||
Gender: 'Female', | ||
Id: 'Kendra', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kendra (neural)', | ||
Engine: 'neural' | ||
}, | ||
'55': { | ||
Gender: 'Female', | ||
Id: 'Kimberly', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kimberly (neural)', | ||
Engine: 'neural' | ||
}, | ||
'56': { | ||
Gender: 'Female', | ||
Id: 'Salli', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Salli (neural)', | ||
Engine: 'neural' | ||
}, | ||
'57': { | ||
Gender: 'Male', | ||
Id: 'Joey', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Joey (neural)', | ||
Engine: 'neural' | ||
}, | ||
'58': { | ||
Gender: 'Male', | ||
Id: 'Justin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Justin (neural)', | ||
Engine: 'neural' | ||
}, | ||
'59': { | ||
Gender: 'Male', | ||
Id: 'Kevin', | ||
LanguageCode: 'en-US', | ||
LanguageName: 'US English', | ||
Name: 'Kevin (neural)', | ||
Engine: 'neural' | ||
}, | ||
'60': { | ||
Gender: 'Female', | ||
Id: 'Camila', | ||
LanguageCode: 'pt-BR', | ||
LanguageName: 'Brazilian Portuguese', | ||
Name: 'Camila (neural)', | ||
Engine: 'neural' | ||
}, | ||
'61': { | ||
Gender: 'Female', | ||
Id: 'Lupe', | ||
LanguageCode: 'es-US', | ||
LanguageName: 'US Spanish', | ||
Name: 'Lupe (neural)', | ||
Engine: 'neural' | ||
} | ||
}; | ||
// °°°°°°°°°°°°° | ||
node.voiceId = (!isNaN(config.voice) ? voices[config.voice].Id : config.voice); // Transform the old number in a new voice ID, by choiching Ivy as default | ||
// Create sonos client | ||
@@ -1148,3 +1014,3 @@ node.SonosClient = new sonos.Sonos(node.sSonosIPAddress); | ||
RED.log.info('SonosPollyTTS: OwnFile .MP3, skip polly, filename: ' + msg); | ||
var newPath = path.join(node.userDir , "ttspermanentfiles" , msg); | ||
var newPath = path.join(node.userDir, "ttspermanentfiles", msg); | ||
PlaySonos(newPath, node); | ||
@@ -1157,3 +1023,3 @@ return; | ||
RED.log.info('SonosPollyTTS: Hailing .MP3, skip polly, filename: ' + msg); | ||
var newPath = path.join(node.userDir , "hailingpermanentfiles" , msg); | ||
var newPath = path.join(node.userDir, "hailingpermanentfiles", msg); | ||
PlaySonos(newPath, node); | ||
@@ -1165,6 +1031,6 @@ return; | ||
var outputFormat = "mp3"; | ||
var filename = getFilename(msg, node.iVoice, node.ssml, outputFormat); | ||
var filename = getFilename(msg, node.voiceId, node.ssml, outputFormat); | ||
// Get real filename, codified. | ||
filename = path.join(node.userDir , "ttsfiles" , filename); | ||
filename = path.join(node.userDir, "ttsfiles", filename); | ||
@@ -1187,3 +1053,3 @@ // Check if cached | ||
TextType: node.ssml ? 'ssml' : 'text', | ||
VoiceId: node.iVoice | ||
VoiceId: node.voiceId | ||
}; | ||
@@ -1190,0 +1056,0 @@ |
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
851106
1402