node-red-contrib-tts-ultimate
Version:
Transforms the text in speech and hear it using Sonos, Google Cast (Chromecast / Nest) or DLNA/UPnP players, or generate an audio file to be used with third parties nodes. Works with voices from Google (without credentials as well), Google TTS, ElevenLabs
219 lines (201 loc) • 10.3 kB
HTML
<script type="text/javascript">
RED.nodes.registerType("ownfileultimate", {
category: 'TTSUltimate',
defaults: {
name: { value: "OwnFile" },
selectedFile: { value: "", required: true },
priority: { value: false }
},
color: '#FFF9FF',
inputs: 1,
outputs: 1,
icon: 'file.png',
paletteLabel: 'Own File',
label: function () {
return this.name || this.selectedFile.replace("OwnFile_", '').replace(".mp3", '');
},
labelStyle: function () {
return this.name ? 'node_label_italic' : '';
},
oneditprepare: function () {
var node = this;
// refreshListaFiles
// ##########################################################
node.refreshListaFiles = () => {
return new Promise((resolve, reject) => {
$("#node-input-selectedFile")
.find('option')
.remove()
.end();
try {
$.getJSON('getOwnFilesList', new Date().getTime(), (data) => {
data.sort().forEach(oFile => {
$("#node-input-selectedFile").append($("<option></option>")
.attr("value", oFile.filename)
.text(oFile.name)
)
});
$("#node-input-selectedFile").val(typeof node.selectedFile === "undefined" ? "" : node.selectedFile)
resolve(true);
});
} catch (error) {
return reject(error);
}
});
}
// ##########################################################
// 27/02/2020 Upload file or files
// ##########################################################
$("#ownFileUpload").change(function (e) {
var oFiles;
oFiles = this.files;
$.each(oFiles, function (i, file) {
var fdata = new FormData();
fdata.append("customTTS", file);
$.ajax({
url: "ttsultimateOwnFile",
type: "POST",
data: fdata, //add the FormData object to the data parameter
processData: false, //tell jquery not to process data
contentType: false,
success: function (response, status, jqxhr) {
if (typeof response === "object" && response.status === 404) {
let myNotification = RED.notify(response.message,
{
modal: true,
fixed: true,
type: 'error',
buttons: [
{
text: "Understood",
click: function (e) {
myNotification.close();
}
}]
});
return;
}
// The only way is to wait some time, then refresh
let t = setTimeout(function () {
node.refreshListaFiles().then((success, error) => {
$("#ownFileUpload").val("");// Otherwise will not re-upload a file with the same name
$("#node-input-selectedFile").val("OwnFile_" + file.name);
});
}, 500);
},
error: function (jqxhr, status, errorMessage) {
let myNotification = RED.notify(errorMessage,
{
modal: true,
fixed: true,
type: 'error',
buttons: [
{
text: "Understood",
click: function (e) {
myNotification.close();
}
}]
});
}
});
});
});
// ##########################################################
// Delete selected file
// ##########################################################
$("#deleteSelectedFile").click(function () {
$.getJSON('deleteOwnFile?FileName=' + $("#node-input-selectedFile").val(), (data) => {
// Refresh the combo
node.refreshListaFiles();
});
});
// ##########################################################
// 28/02/2020 Delete all files
// ##########################################################
$("#deleteAllFiles").click(function () {
var checkResult = "Are you sure you want to delete all custom files?";
var myNotification = RED.notify(checkResult,
{
modal: true,
fixed: true,
type: 'info',
buttons: [
{
text: "DELETE ALL",
click: function (e) {
myNotification.close();
var checkResult = "The operation cannot be undone. Are you really sure to delete all custom files?";
var myNotification2 = RED.notify(checkResult,
{
modal: true,
fixed: true,
type: 'warning',
buttons: [
{
text: "ABORT",
click: function (e) {
myNotification2.close();
}
},
{
text: "CONFIRM DELETE",
click: function (e) {
$.getJSON("deleteOwnFile?FileName=DELETEallFiles", (data) => {
node.refreshListaFiles();
});
myNotification2.close();
}
}]
});
myNotification.close();
}
},
{
text: "ABORT",
click: function (e) {
myNotification.close();
}
}]
});
});
// ##########################################################
node.refreshListaFiles();
}
});
</script>
<script type="text/html" data-template-name="ownfileultimate">
<div class="form-row">
<b>OwnFile configuration</b>    <span style="color:red"><i class="fa fa-question-circle"></i> <a target="_blank" href="https://github.com/Supergiovane/node-red-contrib-tts-ultimate"><u>Help online</u></a></span>
<br/>
<br/>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> Name</label>
<input type="text" id="node-input-name" placeholder="Own File">
</div>
<div class="form-row">
<label for="node-input-selectedFile"><i class="fa fa-file-audio-o"></i> File to be played</label>
<select id="node-input-selectedFile"></select> <input id="deleteSelectedFile" type="button" value="DELETE" style="width:100px">
</div>
<div class="form-row">
<label><i class="fa fa-upload"></i> Upload files</label>
<input id="ownFileUpload" type="file" multiple="multiple">
</div>
<div class="form-row">
<label><i class="fa fa-file-audio-o"></i> ALL FILES</label>
<input id="deleteAllFiles" type="button" value="DELETE" style="width:100px">
</div>
<div class="form-row">
<label for="node-input-priority"><i class="fa fa-warning"></i> Priority</label>
<input type="checkbox" id="node-input-priority" style="margin-left: 0px; vertical-align: top; width: auto !important;"> <label style="width:auto !important;"> This node has the priority</label>
</div>
</script>
<script type="text/markdown" data-help-name="ownfileultimate">
<p>
<a href="https://www.paypal.me/techtoday" target="_blank"><img src='https://img.shields.io/badge/Donate-PayPal-blue.svg?style=flat-square' width='30%'></a>
</p>
<p>
Configuration help is in the <a href="https://github.com/Supergiovane/node-red-contrib-tts-ultimate/blob/master/README.md">README</a><br/>
</p>
</script>