Ok, so i'm trying to make a push notification for my discord.
i found this script online.
but it will not post the embed....
This is my monitor code:
TwitchMonitor.onChannelLiveUpdate((streamData) => {
const isLive = streamData.type === "live";
// Refresh channel list
try {
syncServerList(false);
} catch (e) { }
// Update activity
StreamActivity.setChannelOnline(streamData);
// Generate message
const msgFormatted = `${streamData.user_name} is nu live op twitch <:bday:967848861613826108> kom je ook?`;
const msgEmbed = LiveEmbed.createForStream(streamData);
// Broadcast to all target channels
let anySent = false;
for (let i = 0; i < targetChannels.length; i++) {
const discordChannel = targetChannels[i];
const liveMsgDiscrim = `${discordChannel.guild.id}_${discordChannel.name}_${streamData.id}`;
if (discordChannel) {
try {
// Either send a new message, or update an old one
let existingMsgId = messageHistory[liveMsgDiscrim] || null;
if (existingMsgId) {
// Fetch existing message
discordChannel.messages.fetch(existingMsgId)
.then((existingMsg) => {
existingMsg.edit(msgFormatted, {
embed: msgEmbed
}).then((message) => {
// Clean up entry if no longer live
if (!isLive) {
delete messageHistory[liveMsgDiscrim];
liveMessageDb.put('history', messageHistory);
}
});
})
.catch((e) => {
// Unable to retrieve message object for editing
if (e.message === "Unknown Message") {
// Specific error: the message does not exist, most likely deleted.
delete messageHistory[liveMsgDiscrim];
liveMessageDb.put('history', messageHistory);
// This will cause the message to be posted as new in the next update if needed.
}
});
} else {
// Sending a new message
if (!isLive) {
// We do not post "new" notifications for channels going/being offline
continue;
}
// Expand the message with a #mention for "here" or "everyone"
// We don't do this in updates because it causes some people to get spammed
let mentionMode = (config.discord_mentions && config.discord_mentions[streamData.user_name.toLowerCase()]) || null;
if (mentionMode) {
mentionMode = mentionMode.toLowerCase();
if (mentionMode === "Nu-Live") {
// Reserved # keywords for discord that can be mentioned directly as text
mentionMode = `#${mentionMode}`;
} else {
// Most likely a role that needs to be translated to <#&id> format
let roleData = discordChannel.guild.roles.cache.find((role) => {
return (role.name.toLowerCase() === mentionMode);
});
if (roleData) {
mentionMode = `<#&${roleData.id}>`;
} else {
console.log('[Discord]', `Cannot mention role: ${mentionMode}`,
`(does not exist on server ${discordChannel.guild.name})`);
mentionMode = null;
}
}
}
let msgToSend = msgFormatted;
if (mentionMode) {
msgToSend = msgFormatted + ` ${mentionMode}`
}
let msgOptions = {
embed: msgEmbed
};
discordChannel.send(msgToSend, msgOptions)
.then((message) => {
console.log('[Discord]', `Sent announce msg to #${discordChannel.name} on ${discordChannel.guild.name}`)
messageHistory[liveMsgDiscrim] = message.id;
liveMessageDb.put('history', messageHistory);
})
.catch((err) => {
console.log('[Discord]', `Could not send announce msg to #${discordChannel.name} on ${discordChannel.guild.name}:`, err.message);
});
}
anySent = true;
} catch (e) {
console.warn('[Discord]', 'Message send problem:', e);
}
}
}
liveMessageDb.put('history', messageHistory);
return anySent;
});
This is the embed code:
const Discord = require('discord.js');
const moment = require('moment');
const humanizeDuration = require("humanize-duration");
const config = require('../data/config.json');
class LiveEmbed {
static createForStream(streamData) {
const isLive = streamData.type === "live";
const allowBoxArt = config.twitch_use_boxart;
let msgEmbed = new Discord.MessageEmbed();
msgEmbed.setColor(isLive ? "RED" : "BLACK");
msgEmbed.setURL(`https://twitch.tv/${(streamData.login || streamData.user_name).toLowerCase()}`);
// Thumbnail
let thumbUrl = streamData.profile_image_url;
if (allowBoxArt && streamData.game && streamData.game.box_art_url) {
thumbUrl = streamData.game.box_art_url;
thumbUrl = thumbUrl.replace("{width}", "288");
thumbUrl = thumbUrl.replace("{height}", "384");
}
msgEmbed.setThumbnail(thumbUrl);
if (isLive) {
// Title
msgEmbed.setTitle(`:red_circle: **${streamData.user_name} is live op Twitch!**`);
msgEmbed.addField("Title", streamData.title, false);
} else {
msgEmbed.setTitle(`:white_circle: ${streamData.user_name} was live op Twitch.`);
msgEmbed.setDescription('The stream has now ended.');
msgEmbed.addField("Title", streamData.title, true);
}
// Add game
if (streamData.game) {
msgEmbed.addField("Game", streamData.game.name, false);
}
if (isLive) {
// Add status
msgEmbed.addField("Status", isLive ? `Live with ${streamData.viewer_count} viewers` : 'Stream has ended', true);
// Set main image (stream preview)
let imageUrl = streamData.thumbnail_url;
imageUrl = imageUrl.replace("{width}", "1280");
imageUrl = imageUrl.replace("{height}", "720");
let thumbnailBuster = (Date.now() / 1000).toFixed(0);
imageUrl += `?t=${thumbnailBuster}`;
msgEmbed.setImage(imageUrl);
// Add uptime
let now = moment();
let startedAt = moment(streamData.started_at);
msgEmbed.addField("Uptime", humanizeDuration(now - startedAt, {
delimiter: ", ",
largest: 2,
round: true,
units: ["y", "mo", "w", "d", "h", "m"]
}), true);
}
return msgEmbed;
}
}
module.exports = LiveEmbed;
But it won't post the embed, only the msg. as you can see it updates teh msg aswell.
enter image description here
i'm stuck on this for four days now, can someone help?
All things are going right, when I try to log array it writes everything true but when I try to return as response, it goes empty to front-end. I'm not sure why this is happening, the normal messages array works fine. I don't know why.
console.log('messageye girdi');
MessageModel.find({
receiver: req.body.uuid,
read: false
}).then((Messages) => {
function removeDups(names) {
let unique = {};
names.forEach(function(i) {
if (!unique[i]) {
unique[i] = true;
}
});
return Object.keys(unique);
}
let Users = [];
Messages.forEach(Message => {
Users.push(Message.sender);
})
const nonduplicate = removeDups(Users);
console.log(nonduplicate);
const MessageUsers = [];
var bu = 0;
nonduplicate.forEach(User => {
UserModel.findOne({
uuid: User
}).then((UserData) => {
console.log(UserData.username);
MessageUsers.push(UserData.username);
console.log(MessageUsers);
})
bu++;
if (bu = nonduplicate.length) {
console.log("bu mu acaba " + JSON.stringify(MessageUsers));
let ArrayVer = Object.assign({}, MessageUsers);
return res.send({
success: true,
users: MessageUsers
});
}
});
I have implemented a service which streams camera output on html5. But it works only if I use localhost:8080 localhost if I use IP address or machine name then it does not even detect the camera.
/*global logger*/
/*
VisualInspection
========================
#file : VisualInspection.js
#version : 1.0.0
#author :
#date : 7/28/2019
#copyright :
#license : Apache 2
Documentation
========================
Describe your widget here.
*/
// Required module list. Remove unnecessary modules, you can always get them back from the boilerplate.
define([
"dojo/_base/declare",
"mxui/widget/_WidgetBase",
"dijit/_TemplatedMixin",
"mxui/dom",
"dojo/dom",
"dojo/dom-prop",
"dojo/dom-geometry",
"dojo/dom-class",
"dojo/dom-style",
"dojo/dom-construct",
"dojo/_base/array",
"dojo/_base/lang",
"dojo/text",
"dojo/html",
"dojo/_base/event",
"VisualInspection/lib/jquery-1.11.2",
"dojo/text!VisualInspection/widget/template/VisualInspection.html",
"VisualInspection/widget/template/tf.min",
// "dojo/text!VisualInspection/widget/template/labels.json",
// "dojo/text!VisualInspection/widget/template/model.json"
], function (declare, _WidgetBase, _TemplatedMixin, dom, dojoDom, dojoProp, dojoGeometry, dojoClass, dojoStyle, dojoConstruct, dojoArray, lang, dojoText, dojoHtml, dojoEvent, _jQuery, widgetTemplate, tf) {
"use strict";
var $ = _jQuery.noConflict(true);
var LABELS_URL = "http://pni6w2465:7777/EasyPlan/model_web/labels.json"
var MODEL_JSON = "http://pni6w2465:7777/EasyPlan/model_web/model.json"
// var tf = require(['../../VisualInspection/node_modules/#tensorflow/tfjs']);
//////////////
const TFWrapper = model => {
const calculateMaxScores = (scores, numBoxes, numClasses) => {
const maxes = []
const classes = []
for (let i = 0; i < numBoxes; i++) {
let max = Number.MIN_VALUE
let index = -1
for (let j = 0; j < numClasses; j++) {
if (scores[i * numClasses + j] > max) {
max = scores[i * numClasses + j]
index = j
}
}
maxes[i] = max
classes[i] = index
}
return [maxes, classes]
}
const buildDetectedObjects = (
width,
height,
boxes,
scores,
indexes,
classes
) => {
const count = indexes.length
const objects = []
for (let i = 0; i < count; i++) {
const bbox = []
for (let j = 0; j < 4; j++) {
bbox[j] = boxes[indexes[i] * 4 + j]
}
const minY = bbox[0] * height
const minX = bbox[1] * width
const maxY = bbox[2] * height
const maxX = bbox[3] * width
bbox[0] = minX
bbox[1] = minY
bbox[2] = maxX - minX
bbox[3] = maxY - minY
objects.push({
bbox: bbox,
class: classes[indexes[i]],
score: scores[indexes[i]]
})
}
return objects
}
var img = null;
const detect = input => {
const batched = tf.tidy(() => {
const img = tf.browser.fromPixels(input)
// Reshape to a single-element batch so we can pass it to executeAsync.
// var img = null;
// //sid
// var canvas = document.querySelector("#canvasElement");
// if (canvas.getContext) {
// var ctx = canvas.getContext("2d");
// img = canvas.toDataURL("image/png");
// }
return img.expandDims(0)
})
const height = batched.shape[1]
const width = batched.shape[2]
// const height = img.height
// const width = img.width
return model.executeAsync(batched).then(result => {
const scores = result[0].dataSync()
const boxes = result[1].dataSync()
// clean the webgl tensors
batched.dispose()
tf.dispose(result)
const [maxScores, classes] = calculateMaxScores(
scores,
result[0].shape[1],
result[0].shape[2]
)
const prevBackend = tf.getBackend()
// run post process in cpu
tf.setBackend('cpu')
const indexTensor = tf.tidy(() => {
const boxes2 = tf.tensor2d(boxes, [
result[1].shape[1],
result[1].shape[3]
])
return tf.image.nonMaxSuppression(
boxes2,
maxScores,
20, // maxNumBoxes
0.5, // iou_threshold
0.5 // score_threshold
)
})
const indexes = indexTensor.dataSync()
indexTensor.dispose()
// restore previous backend
tf.setBackend(prevBackend)
return buildDetectedObjects(
width,
height,
boxes,
maxScores,
indexes,
classes
)
})
}
return {
detect: detect
}
}
//////////////////////
// Declare widget's prototype.
return declare("VisualInspection.widget.VisualInspection", [_WidgetBase, _TemplatedMixin], {
// _TemplatedMixin will create our dom node using this HTML template.
templateString: widgetTemplate,
// DOM elements
inputNodes: null,
colorSelectNode: null,
colorInputNode: null,
infoTextNode: null,
// Parameters configured in the Modeler.
mfToExecute: "",
messageString: "",
backgroundColor: "",
// Internal variables. Non-primitives created in the prototype are shared between all widget instances.
_handles: null,
_contextObj: null,
_alertDiv: null,
_readOnly: false,
// dojo.declare.constructor is called to construct the widget instance. Implement to initialize non-primitive properties.
constructor: function () {
logger.debug(this.id + ".constructor");
this._handles = [];
},
// dijit._WidgetBase.postCreate is called after constructing the widget. Implement to do extra setup work.
postCreate: function () {
logger.debug(this.id + ".postCreate");
if (this.readOnly || this.get("disabled") || this.readonly) {
this._readOnly = true;
}
this._updateRendering();
this._setupEvents();
var video = document.querySelector("#videoElement");
var canvas = document.querySelector("#canvasElement");
// if (navigator.mediaDevices.getUserMedia) {
// navigator.mediaDevices.getUserMedia({ video: true })
// .then(function (stream) {
// video.srcObject = stream;
// })
// .catch(function (err0r) {
// console.log("Something went wrong!");
// });
// }
this.componentDidMount();
},
////////////////////////////////////////////////////////
componentDidMount: function () {
var video = document.querySelector("#videoElement");
if (navigator.mediaDevices && navigator.mediaDevices.getUserMedia) {
const webCamPromise = navigator.mediaDevices
.getUserMedia({
audio: false,
video: {
facingMode: 'user'
}
})
.then(stream => {
window.stream = stream
video.srcObject = stream
return new Promise((resolve, _) => {
video.onloadedmetadata = () => {
resolve()
}
})
})
const modelPromise = tf.loadGraphModel(MODEL_JSON)
const labelsPromise = fetch(LABELS_URL).then(data => data.json())
Promise.all([modelPromise, labelsPromise, webCamPromise])
.then(values => {
const [model, labels] = values
this.detectFrame(video, model, labels)
})
.catch(error => {
console.error(error)
})
}
},
detectFrame: function (video, model, labels) {
TFWrapper(model)
.detect(video)
.then(predictions => {
this.renderPredictions(predictions, labels)
requestAnimationFrame(() => {
this.detectFrame(video, model, labels)
})
})
},
renderPredictions: function (predictions, labels) {
var canvas = document.querySelector("#canvasElement");
const ctx = canvas.getContext('2d')
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height)
// Font options.
const font = '16px sans-serif'
ctx.font = font
ctx.textBaseline = 'top'
predictions.forEach(prediction => {
const x = prediction.bbox[0]
const y = prediction.bbox[1]
const width = prediction.bbox[2]
const height = prediction.bbox[3]
const label = labels[parseInt(prediction.class)]
// Draw the bounding box.
ctx.strokeStyle = '#00FFFF'
ctx.lineWidth = 4
ctx.strokeRect(x, y, width, height)
// Draw the label background.
ctx.fillStyle = '#00FFFF'
const textWidth = ctx.measureText(label).width
const textHeight = parseInt(font, 10) // base 10
ctx.fillRect(x, y, textWidth + 4, textHeight + 4)
})
predictions.forEach(prediction => {
const x = prediction.bbox[0]
const y = prediction.bbox[1]
const label = labels[parseInt(prediction.class)]
// Draw the text last to ensure it's on top.
ctx.fillStyle = '#000000'
ctx.fillText(label, x, y)
})
},
///////////////////////////////////////////////////////////
// mxui.widget._WidgetBase.update is called when context is changed or initialized. Implement to re-render and / or fetch data.
update: function (obj, callback) {
logger.debug(this.id + ".update");
this._contextObj = obj;
this._resetSubscriptions();
this._updateRendering(callback); // We're passing the callback to updateRendering to be called after DOM-manipulation
},
// mxui.widget._WidgetBase.enable is called when the widget should enable editing. Implement to enable editing if widget is input widget.
enable: function () {
logger.debug(this.id + ".enable");
},
// mxui.widget._WidgetBase.enable is called when the widget should disable editing. Implement to disable editing if widget is input widget.
disable: function () {
logger.debug(this.id + ".disable");
},
// mxui.widget._WidgetBase.resize is called when the page's layout is recalculated. Implement to do sizing calculations. Prefer using CSS instead.
resize: function (box) {
logger.debug(this.id + ".resize");
},
// mxui.widget._WidgetBase.uninitialize is called when the widget is destroyed. Implement to do special tear-down work.
uninitialize: function () {
logger.debug(this.id + ".uninitialize");
// Clean up listeners, helper objects, etc. There is no need to remove listeners added with this.connect / this.subscribe / this.own.
},
// We want to stop events on a mobile device
_stopBubblingEventOnMobile: function (e) {
logger.debug(this.id + "._stopBubblingEventOnMobile");
if (typeof document.ontouchstart !== "undefined") {
dojoEvent.stop(e);
}
},
// Attach events to HTML dom elements
_setupEvents: function () {
logger.debug(this.id + "._setupEvents");
this.connect(this.colorSelectNode, "change", function (e) {
// Function from mendix object to set an attribute.
this._contextObj.set(this.backgroundColor, this.colorSelectNode.value);
});
this.connect(this.infoTextNode, "click", function (e) {
// Only on mobile stop event bubbling!
this._stopBubblingEventOnMobile(e);
// If a microflow has been set execute the microflow on a click.
if (this.mfToExecute !== "") {
this._execMf(this.mfToExecute, this._contextObj.getGuid());
}
});
},
_execMf: function (mf, guid, cb) {
logger.debug(this.id + "._execMf");
if (mf && guid) {
mx.ui.action(mf, {
params: {
applyto: "selection",
guids: [guid]
},
callback: lang.hitch(this, function (objs) {
if (cb && typeof cb === "function") {
cb(objs);
}
}),
error: function (error) {
console.debug(error.description);
}
}, this);
}
},
// Rerender the interface.
_updateRendering: function (callback) {
logger.debug(this.id + "._updateRendering");
// Important to clear all validations!
this._clearValidations();
// The callback, coming from update, needs to be executed, to let the page know it finished rendering
this._executeCallback(callback, "_updateRendering");
},
// Handle validations.
_handleValidation: function (validations) {
logger.debug(this.id + "._handleValidation");
this._clearValidations();
var validation = validations[0],
message = validation.getReasonByAttribute(this.backgroundColor);
if (this._readOnly) {
validation.removeAttribute(this.backgroundColor);
} else if (message) {
this._addValidation(message);
validation.removeAttribute(this.backgroundColor);
}
},
// Clear validations.
_clearValidations: function () {
logger.debug(this.id + "._clearValidations");
dojoConstruct.destroy(this._alertDiv);
this._alertDiv = null;
},
// Show an error message.
_showError: function (message) {
logger.debug(this.id + "._showError");
if (this._alertDiv !== null) {
dojoHtml.set(this._alertDiv, message);
return true;
}
this._alertDiv = dojoConstruct.create("div", {
"class": "alert alert-danger",
"innerHTML": message
});
dojoConstruct.place(this._alertDiv, this.domNode);
},
// Add a validation.
_addValidation: function (message) {
logger.debug(this.id + "._addValidation");
this._showError(message);
},
// Reset subscriptions.
_resetSubscriptions: function () {
logger.debug(this.id + "._resetSubscriptions");
// Release handles on previous object, if any.
this.unsubscribeAll();
// When a mendix object exists create subscribtions.
if (this._contextObj) {
this.subscribe({
guid: this._contextObj.getGuid(),
callback: lang.hitch(this, function (guid) {
this._updateRendering();
})
});
this.subscribe({
guid: this._contextObj.getGuid(),
attr: this.backgroundColor,
callback: lang.hitch(this, function (guid, attr, attrValue) {
this._updateRendering();
})
});
this.subscribe({
guid: this._contextObj.getGuid(),
val: true,
callback: lang.hitch(this, this._handleValidation)
});
}
},
_executeCallback: function (cb, from) {
logger.debug(this.id + "._executeCallback" + (from ? " from " + from : ""));
if (cb && typeof cb === "function") {
cb();
}
}
});
});
require(["VisualInspection/widget/VisualInspection"]);
<div id="container">
<video autoplay="true" playsInline="true" width="600" height="500" id="videoElement" style="position: fixed;" >
</video>
<canvas id= "canvasElement" width="600" height="500" style="position: absolute;">
</canvas>
</div>
From Above code, When I run using localhost this code will execute :
<!-- begin snippet: js hide: false console: true babel: false -->
When I run using machine name or IP name :
This code is not considered in developer tool of chrome due to security or some reason
I have drift's async script code in the index.html file of the react app.
<script>
"use strict";
!function () {
var t = window.driftt = window.drift = window.driftt || [];
if (!t.init) {
if (t.invoked) return void (window.console && console.error && console.error("Drift snippet included twice."));
t.invoked = !0, t.methods = ["identify", "config", "track", "reset", "debug", "show", "ping", "page", "hide", "off", "on"],
t.factory = function (e) {
return function () {
var n = Array.prototype.slice.call(arguments);
return n.unshift(e), t.push(n), t;
};
}, t.methods.forEach(function (e) {
t[e] = t.factory(e);
}), t.load = function (t) {
var e = 3e5, n = Math.ceil(new Date() / e) * e, o = document.createElement("script");
o.type = "text/javascript", o.async = !0, o.crossorigin = "anonymous", o.src = "https://js.driftt.com/include/" + n + "/" + t + ".js";
var i = document.getElementsByTagName("script")[0];
i.parentNode.insertBefore(o, i);
};
}
}();
drift.SNIPPET_VERSION = '0.3.1';
drift.load('----api----');
drift.on('ready', api => {
api.widget.hide();
})
</script>
The issue is, it is getting popped up in every page of the app whereas I want it only when I click a button(onClick)
The function to trigger onClick :
openDriftChat = () =>{
const { setDriftState } = this.props;
if (window.drift.api) {
//this needs to happen only once but currently happening on every page load
if (!this.props.driftInit) {
if (localStorage.token) {
var tokenBase64 = localStorage.token.split(".")[1];
var tokenBase64_1 = tokenBase64.replace("-", "+").replace("_", "/");
var token = JSON.parse(window.atob(tokenBase64_1));
window.drift.identify(token.email, {
email: token.email,
nickname: token.name
});
setDriftState(true);
}
}
window.drift.api.openChat();
}
}
I basically want it pop up only when I call the function.
Hello I had the same issue:
To hide the welcome message use the following css code
iframe#drift-widget.drift-widget-welcome-expanded-online {
display: none !important;
}
iframe#drift-widget.drift-widget-welcome-expanded-away {
display: none !important;
}
The welcome message will only be shown when your drift button. Some extra info:
To hide the drift button icon use the following js code
drift.on('ready', function (api) {
api.widget.hide()
drift.on('message', function (e) {
if (!e.data.sidebarOpen) {
api.widget.show()
}
})
drift.on('sidebarClose', function (e) {
if (e.data.widgetVisible) {
api.widget.hide()
}
})
})
To call for the sidebar from a specific button use the following
Javascript
(function () {
var DRIFT_CHAT_SELECTOR = '.drift-open-chat'
function ready(fn) {
if (document.readyState != 'loading') {
fn();
} else if (document.addEventListener) {
document.addEventListener('DOMContentLoaded', fn);
} else {
document.attachEvent('onreadystatechange', function () {
if (document.readyState != 'loading')
fn();
});
}
}
function forEachElement(selector, fn) {
var elements = document.querySelectorAll(selector);
for (var i = 0; i < elements.length; i++)
fn(elements[i], i);
}
function openSidebar(driftApi, event) {
event.preventDefault();
driftApi.sidebar.open();
return false;
}
ready(function () {
drift.on('ready', function (api) {
var handleClick = openSidebar.bind(this, api)
forEachElement(DRIFT_CHAT_SELECTOR, function (el) {
el.addEventListener('click', handleClick);
});
});
});
})();
HTML
<a class="drift-open-chat">Open Chat</a>
I hope this helps someone out there.
PS: The above javascript code must be included after you have initialized your drift widget.
You need to disable that through the application: turn off the Playbooks.
Here is the link to do so: https://app.drift.com/playbooks
Hope it helps.
I've created a React app where I'm using socket.io to connect to the Google Cloud Platform. When I run the client and the server I get following error in the client file:
Uncaught SyntaxError: Identifier 'socket' has already been declared
But I'm not quite sure why since the socket is a constant that is not defined as a global constant. Probably that's not the reason why is failing.
The following is the code of the client.js and the structure of the project:
//connection to socket
const io = require('socket.io-client');
const socket = io.connect('http://localhost:1337');
// ================= visibilitychange =================
// Set the name of the hidden property and the change event for visibility
var hidden, visibilityChange;
if (typeof document.hidden !== "undefined") { // Opera 12.10 and Firefox 18 and later support
hidden = "hidden";
visibilityChange = "visibilitychange";
} else if (typeof document.msHidden !== "undefined") {
hidden = "msHidden";
visibilityChange = "msvisibilitychange";
} else if (typeof document.webkitHidden !== "undefined") {
hidden = "webkitHidden";
visibilityChange = "webkitvisibilitychange";
}
// Warn if the browser doesn't support addEventListener or the Page Visibility API
if (typeof document.addEventListener === "undefined" || hidden === undefined) {
console.log("This demo requires a browser, such as Google Chrome or Firefox, that supports the Page Visibility API.");
} else {
// Handle page visibility change
document.addEventListener(visibilityChange, handleVisibilityChange, false);
}
//================= CONFIG =================
// Stream Audio
let bufferSize = 2048,
AudioContext,
context,
processor,
input,
globalStream;
//vars
let audioElement = document.querySelector('audio'),
finalWord = false,
resultText = document.getElementById('ResultText'),
removeLastWord = true,
streamStreaming = false;
//audioStream constraints
const constraints = {
audio: true,
video: false
};
//================= RECORDING =================
function initRecording() {
socket.emit('startGoogleCloudStream', ''); //init socket Google Speech Connection
streamStreaming = true;
AudioContext = window.AudioContext || window.webkitAudioContext;
context = new AudioContext();
processor = context.createScriptProcessor(bufferSize, 1, 1);
processor.connect(context.destination);
context.resume();
var handleSuccess = function (stream) {
globalStream = stream;
input = context.createMediaStreamSource(stream);
input.connect(processor);
processor.onaudioprocess = function (e) {
microphoneProcess(e);
};
};
navigator.mediaDevices.getUserMedia(constraints)
.then(handleSuccess);
}
function microphoneProcess(e) {
var left = e.inputBuffer.getChannelData(0);
var left16 = convertFloat32ToInt16(left);
socket.emit('binaryData', left16);
}
//================= INTERFACE =================
var startButton = document.getElementById("startRecButton");
if(startButton) {
startButton.addEventListener("click", startRecording);
}
var endButton = document.getElementById("stopRecButton");
if(endButton){
endButton.addEventListener("click", stopRecording)
endButton.disabled = true;
}
function startRecording() {
startButton.disabled = true;
endButton.disabled = false;
initRecording();
}
function stopRecording() {
// waited for FinalWord
startButton.disabled = true;
endButton.disabled = true;
streamStreaming = false;
socket.emit('endGoogleCloudStream', '');
let track = globalStream.getTracks()[0];
track.stop();
input.disconnect(processor);
processor.disconnect(context.destination);
context.close().then(function () {
input = null;
processor = null;
context = null;
AudioContext = null;
startButton.disabled = false;
});
}
//================= SOCKET IO =================
socket.on('connect', function (data) {
console.log('client connected');
socket.emit('join', 'Server Connected to Client');
});
socket.on('endmessages', function (data) {
console.log(data);
resultText.appendChild(document.createTextNode(data));
});
socket.on('speechData', function (data) {
// console.log(data.results[0].alternatives[0].transcript);
// console.log(data.results[0]);
var dataFinal = undefined || data.results[0].isFinal;
if (dataFinal === false) {
// console.log(resultText.lastElementChild);
if (removeLastWord) { resultText.lastElementChild.remove(); }
removeLastWord = true;
//add empty span
let empty = document.createElement('span');
resultText.appendChild(empty);
let edit = data.results[0].alternatives[0].transcript;
resultText.lastElementChild.appendChild(document.createTextNode(edit));
resultText.lastElementChild.appendChild(document.createTextNode('\u00A0'));
} else if (dataFinal === true) {
resultText.lastElementChild.remove();
//add empty span
let empty = document.createElement('span');
var br = document.createElement("br");
resultText.appendChild(empty);
let edit = data.results[0].alternatives[0].transcript;
resultText.lastElementChild.appendChild(document.createTextNode(edit));
resultText.lastElementChild.appendChild(document.createTextNode('\u00A0'));
resultText.appendChild(br);
console.log("Google Speech sent 'final' Sentence.");
finalWord = true;
removeLastWord = false;
}
});
socket.on('end', function (data) {
console.log(data);
});
function handleVisibilityChange() {
if (document[hidden]) {
console.log('handleVisibilityChange:hidden');
if (streamStreaming) {
console.log("end");
socket.emit('leave', 'onbeforeunload stop');
stopRecording();
}
} else {
console.log('handleVisibilityChange:show');
startButton.disabled = false;
endButton.disabled = true;
}
}
//================= SANTAS HELPERS =================
// sampleRateHertz 16000 //saved sound is awefull
function convertFloat32ToInt16(buffer) {
let l = buffer.length;
let buf = new Int16Array(l / 3);
while (l--) {
if (l % 3 == 0) {
buf[l / 3] = buffer[l] * 0xFFFF;
}
}
return buf.buffer
}
This is the architecture of the project:
publicFolder
assetsFolder
cssFolder
fontsFolder
jsFolder
client.1.js
client.js
socket.io.js
socket.io.js.map
index.html
serverFolder
app.js //this is server
src
components
App.js //the wrapper component
ComponentA.js
ComponentB.js
App.css
index.js
resgisterServiceWorker.js
.babelrc
webpack.config.js
I think I've fixed, just by changing the connection to the socket from this:
//connection to socket
const io = require('socket.io-client');
const socket = io.connect('http://localhost:1337');
to this
//connection to socket
const socket = io('http://localhost:1337');