TTS with a websocket:Creating a WAV from binary data fails - node.js

I try to create a WAV from binary data using the websocket connection on a node.js server. I use the BluemixTTS to create the speech. Here is my current code:
'use strict';
const WebSocket = require('ws');
var express = require('express');
var watson = require('watson-developer-cloud');
var vcapServices = require('vcap_services');
var extend = (extend = require('util')._extend);
var fs = require('fs');
var ttsConfig = extend(
{
version: 'v1',
url: 'https://stream.watsonplatform.net/text-to-speech/api',
username: 'myusernamehere',
password: "mypasswordhere"
},
vcapServices.getCredentials('text_to_speech')
);
var ttsAuthService = watson.authorization(ttsConfig);
var websocket;
ttsAuthService.getToken({ url: ttsConfig.url }, function(err, token) {
if (err) {
console.log('Error retrieving token: ', err);
return;
}
var voice = 'en-US_AllisonVoice';
var wsURI = 'wss://stream.watsonplatform.net/text-to-speech/api/v1/synthesize?voice=' +
voice + '&watson-token=' + token;
websocket = new WebSocket(wsURI);
websocket.onopen = function(evt) { onOpen(evt) };
websocket.onclose = function(evt) { onClose(evt) };
websocket.onmessage = function(evt) { onMessage(evt) };
websocket.onerror = function(evt) { onError(evt) };
});
function onOpen(evt) {
var message = {
text: 'Hello world',
accept: 'audio/wav',
timings: ['words']
};
websocket.send(JSON.stringify(message));
}
var messages;
var audioStream = null;
function onMessage(evt) {
if (typeof evt.data === 'string') {
messages += evt.data;
} else {
if(audioStream == null){
audioStream = evt.data;
}else{
audioStream += evt.data;
}
}
}
function onClose(evt) {
console.log(messages);
var wstream = fs.createWriteStream('test.wav');
wstream.write((audioStream));
wstream.end();
}
function onError(evt) {
}
I get the token, trigger the TTS specifying audio/wav, build my buffer in the onMessage method and then write it into a .wav file. Everything seems fine.
However the file is somehow broken, and cannot be opened with any music-player. Do I miss some special encoding ?
Any help is appreciated
Regards,
Rambazamba

As the data contains a buffer one has to write the buffer in the file directly each time you get a message and then close the file stream in the onClose event. Like this:
var messages;
var wstream = fs.createWriteStream('test.wav');
function onMessage(evt) {
if (typeof evt.data === 'string') {
messages += evt.data;
} else {
wstream.write(evt.data)
}
}
function onClose(evt) {
console.log(messages);
wstream.end();
}
function onError(evt) {
}

Related

How can i make the chatbot (bot framework) send an attached file from any folder to the user (NodeJS)?

How can i make the chatbot send an attached file from any folder to the user ?
I have the code below but he doesn't work, he show anything.
Can you help me please.
const { TextPrompt, AttachmentPrompt } = require('botbuilder-dialogs');
constructor(luisRecognizer, bookingDialog) {
super('MainDialog');
this.addDialog(new TextPrompt('TextPrompt'))
.addDialog(new AttachmentPrompt('AttachmentPrompt'))
.addDialog(bookingDialog)
.addDialog(new WaterfallDialog(MAIN_WATERFALL_DIALOG, [
this.introStep.bind(this),
this.sendAttachmentStep.bind(this),
this.finalStep.bind(this)
]));
}
async sendAttachmentStep(stepContext) {
var base64Name = "Book1.xlsx";
var base64Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var base64Url = "http://localhost:49811/v3/attachments/.../views/original";
var att = await stepContext.prompt('AttachmentPrompt', {
name: base64Name,
contentType: base64Type,
contentUrl: base64Url,
});
var nex = await stepContext.next();
return {
att, nex
}
}
You just need to load the file as base64 in to your code:
var fs = require('fs');
function base64_encode(file) {
// read binary data
var bitmap = fs.readFileSync(file);
// convert binary data to base64 encoded string
return new Buffer(bitmap).toString('base64');
}
async sendAttachmentStep(stepContext) {
var base64Name = "Book1.xlsx";
var base64Type = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var file = require(./<yourFile>);
var base64File = base64_encode(file);
var att = await stepContext.prompt('AttachmentPrompt', {
name: base64Name,
contentType: base64Type,
contentUrl: `data:${ base64Type };base64,${ base64File }`,
});
var nex = await stepContext.next();
return {
att, nex
}
}
I have find how to do it, I have used the package axios to have the data and after transform it in base64.
async attachmentsStep(stepContext, next) {
var activity = stepContext.context.activity;
if (activity.attachments && activity.attachments.length > 0) {
var attachment = activity.attachments[0];
var base64Url = attachment.contentUrl;
console.log(process.env.PATH);
var axios = require('axios');
var excel = await axios.get(base64Url, { responseType: 'arraybuffer' });
var base64str = Buffer.from(excel.data).toString('base64');
// base64str = 'data:' + base64Type + ';base64,' + base64str;
this.base64str = base64str;
var nex = await stepContext.next();
return {
base64str,
nex
};
}
}
thanks all of you for your response

Node.js - copy file from FTP A to FTP B by stream

I want to copy data from FTP A to FTP B.
I use stream instead of the local temp file.
But i cannot read the data from stream.
transformComponent.js
const Transform = require('stream').Transform;
const util = require('util');
const transformComponent = module.exports = function(options) {
if (!(this instanceof transformComponent))
return new Parser(options);
Transform.call(this, options);
};
util.inherits(transformComponent, Transform);
transformComponent.prototype._transform = function(data, encoding, callback) {
this.push(data);
callback();
};
transformComponent.prototype._flush = function(callback) {
callback();
};
ftpComponent.js
const Client = require('ftp');
var ftp = new Client();
var ftpComponent = function(host){
this.host = host;
this.port = 21;
this.user = "";
this.password = "";
};
function connectionProperties(){
let properties ={
host: this.host,
port: this.port
};
if(this.user && this.user!== "")
properties.user = this.user;
if(this.password && this.password !== "")
properties.password = this.password;
return properties;
}
function download(filepath, target){
ftp.on('ready', function () {
ftp.get(filepath, function(err, stream) {
if (err) throw err;
stream.once('close', function() { ftp.end(); });
stream.pipe(target);
});
});
ftp.connect(this.connectionProperties());
}
function upload(source, filename){
ftp.on('ready', function () {
// Upload files to the server:
ftp.put(source, filename, function(err) {
if (err) throw err;
ftp.end();
});
});
ftp.connect(this.connectionProperties());
}
ftpComponent.prototype = {
connectionProperties: connectionProperties,
pull : download,
push : upload
}
module.exports = ftpComponent;
My usage :
const ftp = require('./node_component/ftpComponent.js');
const transform = require('./node_component/transformComponent.js');
var ftpSourceObject = new ftp('host A');
var ftpTargetObject = new ftp('host B');
ftpSourceObject.user = usernameA;
ftpSourceObject.password = passwordA;
ftpTargetObject.user = usernameB;
ftpTargetObject.password = passwordB;
var temp = new transform();
ftpTargetObject.push(temp, 'file-cp.txt');
ftpSourceObject.pull('file.txt', temp);
I can write data into stream from FTP A.
But when reading data from stream and put on FTP B.
It shows the error like below.
Error: Unable to parse PASV server response
at Object.reentry [as cb] (/home/locadmin/fileshareservice/app/node_modules/ftp/lib/connection.js:857:19)
at Parser.<anonymous> (/home/locadmin/fileshareservice/app/node_modules/ftp/lib/connection.js:117:20)
at Parser.emit (events.js:182:13)
at Parser._write (/home/locadmin/fileshareservice/app/node_modules/ftp/lib/parser.js:59:10)
at doWrite (_stream_writable.js:410:12)
at writeOrBuffer (_stream_writable.js:394:5)
at Parser.Writable.write (_stream_writable.js:294:11)
at Socket.ondata (/home/locadmin/fileshareservice/app/node_modules/ftp/lib/connection.js:273:20)
at Socket.emit (events.js:182:13)
at addChunk (_stream_readable.js:283:12)
But when i run just a single line
var temp = new transform();
ftpTargetObject.push(temp, 'file-cp.txt');
temp.write('123');
temp.end();
//ftpSourceObject.pull('file.txt', temp);
It work successful.
How can I pass the stream as parameter to function??
Sorry for my poor English...
My source code reference source is https://bountify.co/node-js-script-for-copying-files-between-two-ftp-locations.
I fix it.
transformComponent.js
const Transform = require('stream').Transform;
const util = require('util');
const transformComponent = module.exports = function(options) {
if (!(this instanceof transformComponent))
return new Parser(options);
Transform.call(this, options);
};
util.inherits(transformComponent, Transform);
transformComponent.prototype._transform = function(data, encoding, callback) {
this.push(data);
callback();
};
transformComponent.prototype._flush = function(callback) {
callback();
};
ftpComponent.js
const Client = require('ftp');
var ftpComponent = function(host){
this.host = host;
this.port = 21;
this.user = "";
this.password = "";
};
function connectionProperties(){
let properties ={
host: this.host,
port: this.port
};
if(this.user && this.user!== "")
properties.user = this.user;
if(this.password && this.password !== "")
properties.password = this.password;
return properties;
}
function download(filepath, target){
var ftp = new Client();
ftp.on('ready', function () {
ftp.get(filepath, function(err, stream) {
if (err) throw err;
stream.once('close', function() { ftp.end(); });
stream.pipe(target);
});
});
ftp.connect(this.connectionProperties());
}
function upload(source, filename){
var ftp = new Client();
ftp.on('ready', function () {
// Upload files to the server:
ftp.put(source, filename, function(err) {
if (err) throw err;
ftp.end();
});
});
ftp.connect(this.connectionProperties());
}
ftpComponent.prototype = {
connectionProperties: connectionProperties,
pull : download,
push : upload
}
module.exports = ftpComponent;
My usage :
const ftp = require('./node_component/ftpComponent.js');
const transform = require('./node_component/transformComponent.js');
var ftpSourceObject = new ftp('host A');
var ftpTargetObject = new ftp('host B');
ftpSourceObject.user = usernameA;
ftpSourceObject.password = passwordA;
ftpTargetObject.user = usernameB;
ftpTargetObject.password = passwordB;
var temp = new transform();
ftpTargetObject.push(temp, 'file-cp.txt');
ftpSourceObject.pull('file.txt', temp);

How can I post a GIF image to twitter using Twit library?

I am trying to build a small bot that posts random GIFs to twitter based on a hard-coded category (for now).
I am using Twit library for making posts to twitter using the Twitter API. How can I post a GIF to twitter?
Here's the code :
var twit = require('twit');
var config = require('./config');
var request = require('request');
var fs = require('fs');
var path = require('path');
const GIPHY_API_KEY = 'API-KEY';
const GIPHY_API_URL = 'http://api.giphy.com/v1/gifs/random? api_key='+GIPHY_API_KEY+'&tag=study';
var T = new twit(config);
getAndPostGifImg();
function getAndPostGifImg() {
request(GIPHY_API_URL,function (error,response,body) {
var resp = JSON.parse(body);
var img_url = resp.data.image_url;
console.log(img_url);
// post the image to twitter
postImg(img_url);
});
function postImg(img_url) {
request(img_url).pipe(fs.createWriteStream('images/imgpost.gif'));
var filename = path.join(__dirname,'/images/','imgpost.gif');
var params = { encoding: 'base64' };
var img = fs.readFileSync(filename,params);
T.post('media/upload', { media_data: img }, onUpload);
function onUpload(err,data,response) {
var id = data.media_id_string; console.log(id);
// post a tweet /hashtag along with image
var tweet = { status: 'random Study Tweet #giphyBotTweets', media_ids: [id] };
T.post('statuses/update',tweet, tweeted);
}
function tweeted(err,data,response){
if(err)
{
var errors = data.errors;
var i = 0;
for(i = 0 ; i < errors.length; i++)
console.log("Error Message(s) : "+errors[i].message);
}
else
{ console.log(data.text); }
}
}
}
Thanks in advance.
T.post(
"media/upload",
{
media_data: dataImage,
command: "APPEND",
media_id: data.media_id_string,
segment_index: 0
},
function(err, data2, response2) {
T.post(
"media/upload",
{ command: "FINALIZE", media_id: data.media_id_string },
function(err3, data3, response3) {
let tweet = {
status: post.caption,
media_ids: [id]
};
T.post("statuses/update", tweet, function(
err,
data4,
response
) {
if (err) console.log("Something Went wrong", err.message);
if (data4.errors) {
console.log(
"ERROR On Success : ",
data4.errors[0].message
);
} else {
let update = {status: 2, TwitpublishId: data.media_id, updatedAt: Date.now() },
options = { new: true };
Post.findByIdAndUpdate(post._id, update, options, (error, result) => {
if (error) return;
console.log('result video========twit',result);
console.log("Posted on Twitter : https://twitter.com");
});
}
});
}
);
}
);
}
);
}
}

how to check the progress of file uploading using formdata in node.js?

I want to check the percentage of file uploading in the third server.
below is my controller code.
which upload the file to third server.
BASE.APP.post('/uploadFile/:request/:file', function (req, res, next) {
//var form = new BASE.multiparty.Form();
var path = 'uploads/'+req.params.file;
var fstream = BASE.FS.createReadStream(path);
//form.on('part', function(part) {
// console.log('inside');
var url = req.usersession.webipAddress;
/* var formData = {
file: {
value: BASE.FS.createReadStream(path),
options: {
fileNameUnique: req.params.file
}
}
};
// Post the file to the upload server
BASE.request.post({url: url+'test/service/uploadFile/', formData: formData});*/
/*var form = new BASE.FormData();
form.append('fileNameUnique', req.params.file);
form.append( 'file',fstream);
*/
var formData = {
fileNameUnique: req.params.file,
file: fstream
};
var r = BASE.request.post({url: url+'test/service/uploadFile/', formData: formData}, function(err1, res1, body){
console.log('new method err' + err1);
console.log('new method' + res1);
clearInterval(tasktimeoutId);
tasktimeoutId = false;
res.send(res1);
});
var tasktimeoutId = null;
if(!tasktimeoutId){
tasktimeoutId = setInterval(function(){
console.log('interval inside');
interrupttable.findOne({ "filename": req.params.file }, function(err, thor) {
if (thor!=null)
{
console.log('null inside');
if(thor.status=='interrupt')
{
console.log('interrupt');
r.abort();
r = null;
clearInterval(tasktimeoutId);
tasktimeoutId = false;
res.send("interrupted");
//return
//next(err);
}
}
});
}, 1000);
}
});
is there any way to check the file progress in percentage. So that i can
show the progress bar in front end.
Check this repo: https://github.com/zeMirco/express-upload-progress. It should have what you are looking for :)

WebSocket connection to 'ws://localhost:3434/' failed: Connection closed before receiving a handshake response

When using the cmd to run the node server.js and launch the localhost:3434 in the web browser I am getting the error:
in Chrome:
Connection closed before receiving a handshake response.
in firefox:
Firefox can't establish a connection to the server at ws://localhost:3434/
Could you pls help
server.js
var http = require('http'),
fs = require('fs');
fs.readFile('../index.html', function (err, html) {
if (err) {
throw err;
}
http.createServer(function (request, response) {
response.writeHeader(200, { "Content-Type": "text/html" });
response.write(html);
response.end();
}).listen(3434);
});
index.html
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<!--<script type="text/javascript" src="../../js/adapter.js"></script>-->
<!--<script type="text/javascript" src="../../js/webrtc.js"></script>-->
<title>Simple WebRTC video chat</title>
</head>
<body>
<header>
<video id="localVideo" autoplay="autoplay" muted="muted" style="width:40%;"></video>
<video id="remoteVideo" autoplay="autoplay" style="width:40%;"></video>
<input type="button" id="start" onclick="start(true)" value="Start Video"; />
</header>
<script>
var RTCPeerConnection = null;
var getUserMedia = null;
var attachMediaStream = null;
var reattachMediaStream = null;
var webrtcDetectedBrowser = null;
var webrtcDetectedVersion = null;
function trace(text) {
// This function is used for logging.
if (text[text.length - 1] == '\n') {
text = text.substring(0, text.length - 1);
}
console.log((performance.now() / 1000).toFixed(3) + ": " + text);
}
if (navigator.mozGetUserMedia) {
console.log("This appears to be Firefox");
webrtcDetectedBrowser = "firefox";
webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Firefox\/([0- 9]+)\./)[1]);
// The RTCPeerConnection object.
RTCPeerConnection = mozRTCPeerConnection;
// The RTCSessionDescription object.
RTCSessionDescription = mozRTCSessionDescription;
// The RTCIceCandidate object.
RTCIceCandidate = mozRTCIceCandidate;
// Get UserMedia (only difference is the prefix).
getUserMedia = navigator.mozGetUserMedia.bind(navigator);
// Creates iceServer from the url for FF.
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
if (url_parts[0].indexOf('stun') === 0) {
// Create iceServer with stun url.
iceServer = { 'url': url };
} else if (url_parts[0].indexOf('turn') === 0 &&
(url.indexOf('transport=udp') !== -1 ||
url.indexOf('?transport') === -1)) {
// Create iceServer with turn url.
// Ignore the transport parameter from TURN url.
var turn_url_parts = url.split("?");
iceServer = {
'url': turn_url_parts[0],
'credential': password,
'username': username
};
}
return iceServer;
};
// Attach a media stream to an element.
attachMediaStream = function (element, stream) {
console.log("Attaching media stream");
element.mozSrcObject = stream;
element.play();
};
reattachMediaStream = function (to, from) {
console.log("Reattaching media stream");
to.mozSrcObject = from.mozSrcObject;
to.play();
};
MediaStream.prototype.getVideoTracks = function () {
return [];
};
MediaStream.prototype.getAudioTracks = function () {
return [];
};
} else if (navigator.webkitGetUserMedia) {
console.log("This appears to be Chrome");
webrtcDetectedBrowser = "chrome";
webrtcDetectedVersion =
parseInt(navigator.userAgent.match(/Chrom(e|ium)\/([0-9]+)\./)[2]);
// Creates iceServer from the url for Chrome.
createIceServer = function (url, username, password) {
var iceServer = null;
var url_parts = url.split(':');
if (url_parts[0].indexOf('stun') === 0) {
// Create iceServer with stun url.
iceServer = { 'url': url };
} else if (url_parts[0].indexOf('turn') === 0) {
if (webrtcDetectedVersion < 28) {
var url_turn_parts = url.split("turn:");
iceServer = {
'url': 'turn:' + username + '#' + url_turn_parts[1],
'credential': password
};
} else {
iceServer = {
'url': url,
'credential': password,
'username': username
};
}
}
return iceServer;
};
// The RTCPeerConnection object.
RTCPeerConnection = webkitRTCPeerConnection;
// Get UserMedia (only difference is the prefix).
// Code from Adam Barth.
getUserMedia = navigator.webkitGetUserMedia.bind(navigator);
// Attach a media stream to an element.
attachMediaStream = function (element, stream) {
if (typeof element.srcObject !== 'undefined') {
element.srcObject = stream;
} else if (typeof element.mozSrcObject !== 'undefined') {
element.mozSrcObject = stream;
} else if (typeof element.src !== 'undefined') {
element.src = URL.createObjectURL(stream);
} else {
console.log('Error attaching stream to element.');
}
};
reattachMediaStream = function (to, from) {
to.src = from.src;
};
// The representation of tracks in a stream is changed in M26.
// Unify them for earlier Chrome versions in the coexisting period.
if (!webkitMediaStream.prototype.getVideoTracks) {
webkitMediaStream.prototype.getVideoTracks = function () {
return this.videoTracks;
};
webkitMediaStream.prototype.getAudioTracks = function () {
return this.audioTracks;
};
}
if (!webkitRTCPeerConnection.prototype.getLocalStreams) {
webkitRTCPeerConnection.prototype.getLocalStreams = function () {
return this.localStreams;
};
webkitRTCPeerConnection.prototype.getRemoteStreams = function () {
return this.remoteStreams;
};
}
} else {
console.log("Browser does not appear to be WebRTC-capable");
}
var localVideo;
var remoteVideo;
var peerConnection;
var localStream;
var optional = { optional: [{ DtlsSrtpKeyAgreement: true }] }
var peerConnectionConfig = { 'iceServers': [{ 'url': 'stun:stun.services.mozilla.com' }, { 'url': 'stun:stun.l.google.com:19302' }] };
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
localVideo = document.getElementById("localVideo");
remoteVideo = document.getElementById("remoteVideo");
serverConnection = new WebSocket('ws://localhost:3434');
serverConnection.onmessage = gotMessageFromServer;
var constraints = {
video: true,
audio: true,
};
if (navigator.getUserMedia) {
navigator.getUserMedia(constraints, getUserMediaSuccess, getUserMediaError);
} else {
alert('Your browser does not support getUserMedia API');
}
function getUserMediaSuccess(stream) {
localStream = stream;
localVideo.src = window.URL.createObjectURL(stream);
}
function start(isCaller) {
peerConnection = new RTCPeerConnection(peerConnectionConfig, optional);
peerConnection.onicecandidate = gotIceCandidate;
peerConnection.onaddstream = gotRemoteStream;
peerConnection.addStream(localStream);
if (isCaller) {
peerConnection.createOffer(gotDescription, createOfferError);
}
}
function gotMessageFromServer(message) {
if (!peerConnection) start(false);
var signal = JSON.parse(message.data);
if (signal.sdp) {
peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp), function () {
peerConnection.createAnswer(gotDescription, createAnswerError);
});
} else if (signal.ice) {
peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
}
}
function gotIceCandidate(event) {
if (event.candidate != null) {
serverConnection.send(JSON.stringify({ 'ice': event.candidate }));
}
}
function gotDescription(description) {
console.log('got description');
peerConnection.setLocalDescription(description, function () {
serverConnection.send(JSON.stringify({ 'sdp': description }));
}, function () { console.log('set description error') });
}
function gotRemoteStream(event) {
console.log("got remote stream");
remoteVideo.src = window.URL.createObjectURL(event.stream);
}
// Error functions....
function getUserMediaError(error) {
console.log(error);
}
function createOfferError(error) {
console.log(error);
}
function createAnswerError(error) {
console.log(error);
}
</script>
</body>
</html>
In order to handle websocket connections your http-server should handle 'upgrade'-event (see here - https://nodejs.org/api/http.html#http_event_upgrade_1)
For example, here is the working example (it uses ws-module):
var WebSocketServer = require('ws').Server;
var wss = new WebSocketServer({noServer: true});
var http = require('http'),
fs = require('fs');
fs.readFile('../index.html', function (err, html) {
if (err) {
throw err;
}
var server = http.createServer(function (request, response) {
response.writeHeader(200, { "Content-Type": "text/html" });
response.write(html);
response.end();
})
server.listen(3434);
server.on('upgrade', wss.handleUpgrade);
wss.on('connection', function connection(ws) {
ws.on('message', function incoming(message) {
console.log('received: %s', message);
});
ws.send('something');
});
});
Here are docs for ws - https://github.com/websockets/ws

Resources