Watson ignores inactivity timeout while recognizing "audio/wav" - javascript

I try to implement Speech recognititon using Watson Speech To Text service.
I wrote some code in javascript using "MediaStreamRecorder" library. I send data through Websocket and get this problem: if I use "content-type": "audio/wav", Watson recognizes only first blob and set inactivity_timeout to defaul value meanwhile I set it to 2 seconds.
I use this code for opening websocket:
initWebSocket(startRecordingCallback) {
var that = this;
that.websocket = new WebSocket(that.wsURI);
that.websocket.onopen = function (evt) {
console.log("WebSocket: connection OK ");
var message = {
"action": "start",
"content-type": "audio/wav",
"interim_results": true,
"continuous": true,
"inactivity_timeout": 2
};
that.websocket.send(JSON.stringify(message));
};
that.websocket.onclose = function (evt) {
if (event.wasClean) {
console.log("WebSocket: connection closed clearly " + JSON.stringify(evt));
} else {
console.log("WebSocket: disconnect " + JSON.stringify(evt));
}
};
that.websocket.onmessage = function (evt) {
console.log(evt)
};
that.websocket.onerror = function (evt) {
console.log("WebSocket: error " + JSON.stringify(evt));
};
}
And this code for recording audio:
startRecording() {
var that = this;
this.initWebSocket(function () {
var mediaConstraints = {
audio: true
};
function onMediaSuccess(stream) {
that.mediaRecorder = new MediaStreamRecorder(stream);
that.mediaRecorder.mimeType = 'audio/wav';
that.mediaRecorder.ondataavailable = function (blob) {
that.websocket.send(blob);
};
that.mediaRecorder.start(3000);
}
function onMediaError(e) {
console.error('media error', e);
}
navigator.getUserMedia(mediaConstraints, onMediaSuccess, onMediaError);
});
}
I need do recognition in real-time using websocket with socket auto closing after 2 second of inactivity.
Please, advice me.

As #Daniel Bolanos said, inactivity_timeout is not triggered if the transcript is empty for more than inactivity_timeout seconds. The service uses a different way to detect if there is speech rather than relying on the transcription.
If the service detects speech it won't trigger the inactivity_timeout even if the transcript is empty.
Here is a snippet of code that does what you were trying to do with your question but using the speech-javascript-sdk.
Hopefully, it will help future StackOverflow users trying to recognize audio from the microphone.
document.querySelector('#button').onclick = function () {
// you need to provide this endpoint to fetch a watson token
fetch('/api/speech-to-text/token')
.then(function(response) {
return response.text();
}).then(function (token) {
var stream = WatsonSpeech.SpeechToText.recognizeMicrophone({
token: token,
outputElement: '#output' // CSS selector or DOM Element
});
stream.on('error', function(err) {
console.log(err);
});
document.querySelector('#stop').onclick = function() {
stream.stop();
};
}).catch(function(error) {
console.log(error);
});
};
Demo: https://watson-speech.mybluemix.net/microphone-streaming.html
Credits to #Nathan Friedly who wrote the library.

Related

Ratchet PHP reconnect client who loose connection [duplicate]

var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function () {
ws.send(JSON.stringify({
.... some message the I must send when I connect ....
}));
};
ws.onmessage = function (e) {
console.log('Got a message')
console.log(e.data);
};
ws.onclose = function(e) {
console.log('socket closed try again');
}
ws.onerror = function(err) {
console.error(err)
};
When I first connect to the socket, I must first send a message to the server to authenticate myself and subscribe to channels.
The problem I have is that sometimes the socket server is unreliable and that triggers the onerror and onclose events of the 'ws' object.
Question: What is a good design pattern that would allow me, whenever the socket closes or encounters an error, wait for 10 seconds and then reconnect to the socket server (and resend the initial message to the server)
Here is what I ended up with. It works for my purposes.
function connect() {
var ws = new WebSocket('ws://localhost:8080');
ws.onopen = function() {
// subscribe to some channels
ws.send(JSON.stringify({
//.... some message the I must send when I connect ....
}));
};
ws.onmessage = function(e) {
console.log('Message:', e.data);
};
ws.onclose = function(e) {
console.log('Socket is closed. Reconnect will be attempted in 1 second.', e.reason);
setTimeout(function() {
connect();
}, 1000);
};
ws.onerror = function(err) {
console.error('Socket encountered error: ', err.message, 'Closing socket');
ws.close();
};
}
connect();
This worked for me with setInterval, because client connection can be lost.
ngOnInit(): void {
if (window.location.protocol.includes('https')) {
this.protocol = 'wss';
}
this.listenChanges();
}
listenChanges(): void {
this.socket = new WebSocket(`${this.protocol}://${window.location.host}/v1.0/your/url`);
this.socket.onmessage = (event): void => {
// your subscription stuff
this.store.dispatch(someAction);
};
this.socket.onerror = (): void => {
this.socket.close();
};
this.socket.onopen = (): void => {
clearInterval(this.timerId);
this.socket.onclose = (): void => {
this.timerId = setInterval(() => {
this.listenChanges();
}, 10000);
};
};
}
Don't forget to call clearInterval when the socket has been opened.
This isn't explicitly a react question but here is a react style answer:
TLDR: You can use setInterval to periodically check the websocket connection status and try to re-connect if the connection is closed. https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
class TestComponent extends React.Component {
constructor(props) {
super(props);
this.state = {};
this.connect = this.connect.bind(this);
}
componentDidMount() {
this.interval = setInterval(this.connect, 1000);
}
componentWillUnmount() {
if (this.ws) this.ws.close();
if (this.interval) clearInterval(this.interval);
}
connect() {
// https://developer.mozilla.org/en-US/docs/Web/API/WebSocket/readyState
if (this.ws === undefined || (this.ws && this.ws.readyState === 3)) {
this.ws = new WebSocket(`ws://localhost:8080`);
this.ws.onmessage = (e) => {
console.log(JSON.parse(e.data));
};
}
}
render() {
return <div>Hey!</div>;
}
}
I found that this package https://github.com/pladaria/reconnecting-websocket can solve the reconnection issues for Websocket connections. And it has the list of configurable options, one of them is reconnectionDelayGrowFactor which determines how fast the reconnection delay grows.
using async-await if socket closed or any error occurred on the server the client will try to connect automatically every 5 sec forever
have a look to my answer
UPDATED answer:
At last, (if you are not using java) I found you'd better implement your own "ping/pong" strategy. (if you are using java, please take a look at ping/pong "action type", I don't remember very clear... )
client sent "ping" to server every 5 seconds.
server should echo a "pong" to the client once it receive "ping".
client should reconnect server if doesn't receive "pong" in 5 seconds.
Don't rely on any third party libs.
WARNING: DO NOT use these tools: (reason: they are not reliable and not stable and works in a very limited way. )
check if the network is available: https://github.com/hubspot/offline
to re-connect: https://github.com/joewalnes/reconnecting-websocket
You can use a small library if you want - ReconnectingWebSocket
Add reconnecting-websocket.js in your script tag and
It is API compatible, so when you have:
var ws = new WebSocket('ws://....');
you can replace with:
var ws = new ReconnectingWebSocket('ws://....');
Try this:
const observable = Observable.create(
(obs: Observer<MessageEvent>) => {
this.ws.onmessage = obs.next.bind(obs);
this.ws.onerror = obs.error.bind(obs);
// this.ws.onclose = obs.complete.bind(obs);
this.ws.onclose = function () {
window.location.reload()
}
return this.ws.close.bind(this.ws);
});
const observer = {
next: (data: Object) => {
if (this.ws.readyState === WebSocket.OPEN) {
this.ws.send(JSON.stringify(data));
}
}
};
and component
getDatas() {
let url = environment.apiwebsocket
this.webSocketService.connect(url)
.subscribe(evt => {
let jsonObj = JSON.parse(evt.data)
});}
I used to have this somewhere in project:
let rc = new WebSocket(
'ws://'
+ window.location.host
+ `/ws/chat/${window.seen.pk}/`
)
now I switched to:
// ws create the websocket and returns it
function autoReconnect(ws_create){
let ws = ws_create();
function startReconnecting(){
let interval = setInterval(()=>{
console.log('trying')
ws = ws_create();
ws.onopen = () => {
console.log('stop');
ws.onclose = startReconnecting;
clearInterval(interval);
}
}, 3000);
}
ws.onclose = startReconnecting;
}
let rc;
autoReconnect(()=>{
rc = new WebSocket(
'ws://'
+ window.location.host
+ `/ws/chat/${window.seen.pk}/`
)
return rc;
});
test it by running and stop local host, it works fine. (btw I found it weird this question has been posted for a long time, but there is not a short and elegant solution)
the benefit of this method, is that it allows you to pass in an arrow function, so that you can assign variable to any outer scope.
Here's a simple version I use in my projects. It includes an incrementing wait timer for reconnects.
//wsURL - the string URL of the websocket
//waitTimer - the incrementing clock to use if no connection made
//waitSeed - used to reset the waitTimer back to default on a successful connection
//multiplier - how quickly you want the timer to grow on each unsuccessful connection attempt
const openSocket = (wsURL, waitTimer, waitSeed, multiplier) =>{
let ws = new WebSocket(wsURL);
console.log(`trying to connect to: ${ws.url}`);
ws.onopen = () => {
console.log(`connection open to: ${ws.url}`);
waitTimer = waitSeed; //reset the waitTimer if the connection is made
ws.onclose = () => {
console.log(`connection closed to: ${ws.url}`);
openSocket(ws.url, waitTimer, waitSeed, multiplier);
};
ws.onmessage = (message) => {
//do something with messge...
};
};
ws.onerror = () => {
//increaese the wait timer if not connected, but stop at a max of 2n-1 the check time
if(waitTimer < 60000) waitTimer = waitTimer * multiplier;
console.log(`error opening connection ${ws.url}, next attemp in : ${waitTimer/1000} seconds`);
setTimeout(()=>{openSocket(ws.url, waitTimer, waitSeed, multiplier)}, waitTimer);
}
}
openSocket(`ws://localhost:3000`, 1000, 1000, 2)
Alternatively you can explore socket.io. It offers this feature
on the client side you indicate reconnection: true
const io = require("socket.io-client");
const socket = io('ws://'+WS_REMOTE_ADDRESS,{
reconnection: true,
});

Issue with node-rcon

I'm trying to setup a rcon function, and I'm using node-rcon . With the example provided it works perfectly, but with my code, it doesn't work, I can't figure out why. Any clue what's the issue with my code? It throws no errors, but the server doesn't recieve the rcon command. Here's my code:
var Rcon = require('../node-rcon');
console.log('Starting the rcon...');
var conn = new Rcon('localhost', 30120, 'test123', options);
conn.on('auth', function() {
console.log("Authed!");
}).on('response', function(str) {
console.log("Got response: " + str);
}).on('end', function() {
console.log("Socket closed!");
process.exit();
});
conn.connect();
conn.send("say working!");
conn.disconnect();
It's a nodejs, and yes, the example works for me just fine.
I copied your code here and make some changes to work. I hope this helps you.
First, you have to import the correct module after the installation. Second, you have to put your configuration options.
var Rcon = require('rcon');
console.log('Starting the rcon...');
var options = {
tcp: false, // false for UDP, true for TCP (default true)
challenge: false // true to use the challenge protocol (default true)
};
var conn = new Rcon('localhost', 30120, 'test123', options);
conn.on('auth', function() {
console.log("Authed!");
}).on('response', function(str) {
console.log("Got response: " + str);
}).on('end', function() {
console.log("Socket closed!");
process.exit();
});
conn.connect();
conn.send("say working!");
conn.disconnect();
The fix is actually easy, it's just a matter of waiting. This isn't a perfect solution, but it works for what I need.
async function sendmessage(frase){
var conn = new Rcon('IP', 30120, 'PASSWORD', options);
const sleep = ms => new Promise(res => setTimeout(res, ms));
conn.connect();
console.log('Waiting 1 sec...');
await sleep(500);
conn.send(frase);
console.log('Waiting 1 sec...');
await sleep(1000);
conn.disconnect();
return;
Hope this helps someone
I used the respond event from the first command to send the next one
var Rcon = require('rcon');
console.log('Starting the rcon...');
var conn = new Rcon('localhost', 30120, 'test123', options);
var options = {
tcp: false, // false for UDP, true for TCP (default true)
challenge: false // true to use the challenge protocol (default true)
};
queuedCommands = ['command1', 'command2', 'command3']
var i = 0;
function sendnext (i) {
if(i === queuedCommands.length){
conn.disconnect();
return;
}
conn.send(queuedCommands[i]);
return ++i;
}
conn.on('auth', function() {
console.log("Rcon connection successfull");
i = sendnext(i);// to send the first command
}).on('response', function(str) {
console.log(str)
i = sendnext(i);
}).on('error', function(err) {
console.log("Error: " + err);
output.push(err);
});
conn.connect();

peer.js webrtc >> changing stream in runtime

I am developing a cross-plattform application with peer.js and webrtc.
I am using cordova, crosswalk.
Additionaly I am using the webrtc adapter (https://github.com/webrtc/adapter)
My code is based on the webrtc-crosswalk sample. (https://github.com/crosswalk-project/crosswalk-samples)
I want to change the videosource of the stream without creating a new call.
My approche is to remove the tracks of the stream and add the new tracks of the other camera.
The result is that the local video shows the right content, but the callee's remote video freezes.
Probably I am doing a very basic mistake, but i can't find a solution.
I am looking forward to your answers and solutions.
My main codefile is attached.
//Notwendig, um die Dialogfunktion zu aktivieren
document.addEventListener("deviceready", onDeviceReady, false);
function onDeviceReady() {
console.log(navigator.notification);
// Now safe to use device APIs
}
document.addEventListener('DOMContentLoaded', function () {
// PeerJS server location
var SERVER_IP = '172.20.37.147';
var SERVER_PORT = 9000;
// DOM elements manipulated as user interacts with the app
var messageBox = document.querySelector('#messages');
var callerIdEntry = document.querySelector('#caller-id');
var connectBtn = document.querySelector('#connect');
var recipientIdEntry = document.querySelector('#recipient-id');
var dialBtn = document.querySelector('#dial');
var remoteVideo = document.querySelector('#remote-video');
var localVideo = document.querySelector('#local-video');
var cameraTurn = document.querySelector('#camera_turn');
var stop = document.querySelector('#stop');
// the default facing direction
var dir = "environment";
// the ID set for this client
var callerId = null;
// PeerJS object, instantiated when this client connects with its
// caller ID
var peer = null;
// the local video stream captured with getUserMedia()
var localStream = null;
// DOM utilities
var makePara = function (text) {
var p = document.createElement('p');
p.innerText = text;
return p;
};
var addMessage = function (para) {
if (messageBox.firstChild) {
messageBox.insertBefore(para, messageBox.firstChild);
}
else {
messageBox.appendChild(para);
}
};
var logError = function (text) {
var p = makePara('ERROR: ' + text);
p.style.color = 'red';
addMessage(p);
};
var logMessage = function (text) {
addMessage(makePara(text));
};
// get the local video and audio stream and show preview in the
// "LOCAL" video element
// successCb: has the signature successCb(stream); receives
// the local video stream as an argument
var getLocalStream = function (successCb, ask = true) {
if (localStream && successCb) {
successCb(localStream);
}
else {
navigator.mediaDevices.getUserMedia({ audio: true, video: { facingMode: dir } })
.then(function (stream) {
if (localStream == null) {
/* use the stream */
localStream = stream;
}
else {
stream.getTracks().forEach(function (track) {
localStream.addTrack(track);
});
}
localVideo.src = window.URL.createObjectURL(localStream);
if (successCb) {
successCb(stream);
}
})
.catch(function (err) {
/* handle the error */
logError('failed to access local camera');
logError(err.message);
});
}
};
// set the "REMOTE" video element source
var showRemoteStream = function (stream) {
remoteVideo.src = window.URL.createObjectURL(stream);
};
// set caller ID and connect to the PeerJS server
var connect = function () {
callerId = callerIdEntry.value;
if (!callerId) {
logError('please set caller ID first');
return;
}
try {
// create connection to the ID server
peer = new Peer(callerId, { host: SERVER_IP, port: SERVER_PORT });
// hack to get around the fact that if a server connection cannot
// be established, the peer and its socket property both still have
// open === true; instead, listen to the wrapped WebSocket
// and show an error if its readyState becomes CLOSED
peer.socket._socket.onclose = function () {
logError('no connection to server');
peer = null;
};
// get local stream ready for incoming calls once the wrapped
// WebSocket is open
peer.socket._socket.onopen = function () {
getLocalStream();
};
// handle events representing incoming calls
peer.on('call', answer);
}
catch (e) {
peer = null;
logError('error while connecting to server');
}
};
// make an outgoing call
var dial = function () {
if (!peer) {
logError('please connect first');
return;
}
if (!localStream) {
logError('could not start call as there is no local camera');
return
}
var recipientId = recipientIdEntry.value;
if (!recipientId) {
logError('could not start call as no recipient ID is set');
return;
}
getLocalStream(function (stream) {
logMessage('outgoing call initiated');
var call = peer.call(recipientId, stream);
call.on('stream', showRemoteStream);
call.on('error', function (e) {
logError('error with call');
logError(e.message);
});
});
};
// answer an incoming call
var answer = function (call) {
if (!peer) {
logError('cannot answer a call without a connection');
return;
}
if (!localStream) {
logError('could not answer call as there is no localStream ready');
return;
}
//Asks user to answer the call
navigator.notification.confirm(
"Receive a call?",
function (buttonIndex) {
if (buttonIndex === 1) {
//user clicked "yes"
logMessage('incoming call answered');
call.on('stream', showRemoteStream);
call.answer(localStream);
}
else {
//user clicked "no"
logMessage('incoming call denied');
}
}
,
'Incoming Call',
['Yes', 'No']
);
};
function turnDirection() {
if (dir === "user")
return "environment";
else
return "user";
}
var turnCamera = function (call) {
dir = turnDirection();
localStream.getTracks().forEach(function (track) {
track.stop();
localStream.removeTrack(track);
});
getLocalStream(false);
};
var stopCall = function (call) { };
// wire up button events
connectBtn.addEventListener('click', connect);
dialBtn.addEventListener('click', dial);
cameraTurn.addEventListener('click', turnCamera);
stop.addEventListener('click', stopCall);
});
If you remove and then add a new track to a PeerConnection you need to renegotiate the offer-answer to get it working. I will recommend you to use the replaceTrack API to avoid the re-negotiation problem while changing the camera input.

XMPP web client (using strophe.js) taking time to connect with ejabberd server

I have implemented an XMPP client for JavaScript (using strophe.js), for which I am referring to the book Professional XMPP with JavaScript and jQuery by Jack Moffitt.
The book has a great explanation on working of XMPP JavaScript client using "strophe.js".
With my code, the XMPP web client is taking 6 seconds to connect with the XMPP server (ejabberd using BOSH), which is not desirable for my application.
Can some one explain why this is happening?
My XMPP client code is as below:
var Arthur = {
connection: null,
jid:"20147001#localhost",
password: "XXXX2014",
handle_message: function (message) {
if ($(message).attr('from')) {
if($(message).attr('from').match(/^abcd007#localhost/)){
console.log("inside message received");
var body = $(message).find('body').contents();
var span = $("<span></span>");
body.each(function () {
if (document.importNode) {
$(document.importNode(this, true)).appendTo(span);
console.log(span);
console.log(span.text());
}
});
notiReceived(span.text());
console.log("afte notiReceived executed");
}
if($(message).attr('from').match(/^xyz2014#localhost/)){
console.log("inside message received");
var body1 = $(message).find('body').contents();
var span1 = $("<span></span>");
body1.each(function () {
if (document.importNode) {
$(document.importNode(this, true)).appendTo(span1);
//console.log(span.find('text'));
console.log(span1);
console.log(span1.text());
}
});
notiReceived(span1.text());
console.log("afte notiReceived executed");
}
}
return true;
}
};
function sendPushNotification(to,operation,request_id,message){
if(to=="citizen"){
var myObject = new Object();
myObject.FROM="Executive";
myObject.FUNCTION=operation;
myObject.MESSAGE = message;
myObject.REQUESTID= request_id;
console.log("inside citizen::"+myObject);
var myString = JSON.stringify(myObject);
$(this).val('');
var msg = $msg({to: 'abcd007#localhost', type: 'chat'})
.c('body').t(myString);
console.log("inside keypress data is::"+msg);
Arthur.connection.send(msg);
}
if(to=="technician"){
var myObject1 = new Object();
myObject1.FROM="Executive";
myObject1.FUNCTION=operation;
myObject1.MESSAGE = "Check Request Status";
myObject1.REQUESTID= request_id;
console.log("inside technician:"+myObject1);
var myString1 = JSON.stringify(myObject1);
$(this).val('');
var msg1 = $msg({to: 'xyz2014#localhost', type: 'chat'})
.c('body').t(myString1);
console.log("after msg send to technician"+msg1);
Arthur.connection.send(msg1);
}
};
function connected() {
console.log("inside connected");
Arthur.connection.addHandler(Arthur.handle_message,
null, "message", "chat");
console.log("inside connected");
Arthur.connection.send($pres());
};
function disconnected() {
console.log("disconnected");
Arthur.connection = null;
};
function disconnect(){
Arthur.connection.disconnect();
};
function connectXMPP() {
var conn = new Strophe.Connection(
hosturl.URL+":5280/http-bind");
console.log("inside connection");
conn.connect(Arthur.jid, Arthur.password, function (status) {
if (status === Strophe.Status.CONNECTED) {
connected();
console.log("connected");
} else if (status === Strophe.Status.DISCONNECTED) {
disconnected();
}
});
Arthur.connection = conn;
};
I don't know whether this is the case here, but in general when connections take long to established, the cause is often a host name resolution issue.
For instance, if a host has both an IPv4 and IPv6 address, but there is no IPv6 connectivity yet IPv6 is tried first, then you may get a delay until the IPv6 connection attempt has timed out.
To examine whether domain name resolution is the cause, you might want to take a look at the network traffic using a tool such as Wireshark.

how to prevent new connection on every page refresh in sockjs

So, every time I refresh the page, it seems like sockjs is creating a new connection.
I am saving every message to my mongodb on every channel.onmessage, so if I refresh my page 7 times and send a message, I would save 7 messages of the same content into my mongodb.
This is very problematic because when I retrieve those messages when I go into the chat room, to see the log, I would see bunch of duplicate messages.
I want to keep track of all connections that are 'active', and if a user tries to make another connection, I want to terminate the old one so there is only one connection listening to each message at a time.
How do I do this ?
var connections = {};
//creating the sockjs server
var chat = sockjs.createServer();
//installing handlers for sockjs server instance, with the same url as client
chat.installHandlers(server, {prefix:'/chat/private'});
var multiplexer = new multiplexServer.MultiplexServer(chat);
var configChannel = function (channelId, userId, userName){
var channel = multiplexer.registerChannel(channelId);
channel.on('connection', function (conn) {
// console.log('connection');
console.log(connections);
connections[channelId] = connections[channelId] || {};
if (connections[channelId][userId]) {
//want to close the extra connection
} else {
connections[channelId][userId] = conn;
}
// }
// if (channels[channelId][userId]) {
// conn = channels[channelId][userId];
// } else {
// channels[channelId][userId] = conn;
// }
// console.log('accessing channel! ', channels[channelId]);
conn.on('new user', function (data, message) {
console.log('new user! ', data, message);
});
// var number = connections.length;
conn.on('data', function(message) {
var messageObj = JSON.parse(message);
handler.saveMessage(messageObj.channelId, messageObj.user, messageObj.message);
console.log('received the message, ', messageObj.message);
conn.write(JSON.stringify({channelId: messageObj.channelId, user: messageObj.user, message: messageObj.message }));
});
conn.on('close', function() {
conn.write(userName + ' has disconnected');
});
});
return channel;
};
The way I resolve a problem like yours was with a Closure and Promises, I don't know if that could help you. I let you the code that help me, this is with EventBus from Vertx:
window.Events = (function NewEvents() {
var eventBusUrl = $('#eventBusUrl').val();
var eventBus = null;
return new RSVP.Promise(function(resolve, reject) {
if(!eventBus) {
eventBus = new vertx.EventBus(eventBusUrl);
eventBus.onopen = function eventBusOpened() {
console.log('Event bus online');
resolve(eventBus);
}
eventBus.onclose = function() {
eventBus = null;
};
}
});
}());
And then in other script I call it in this way:
Events.then(function(eventBus) {
console.log("registering handlers for comments");
eventBus.registerHandler(address, function(incomingMessage) {
console.log(incomingMessage);
});
});
I hope this can help you.
Regards.

Categories