node js create video stream from images sequence - node.js

I get images from python opencv then I want show images to user as video stream on browser.
Images came on sequence. I do this in python Flask with "multipart/x-mixed-replace" but I can`t find same function on node js.

//index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/2.2.0/socket.io.js"></script>
</head>
<body>
<img id="image">
<script>
const socket = io.connect('http://localhost:3000');
socket.on('image', (image) => {
const imageElement = document.getElementById('image');
console.log(imageElement);
imageElement.src = `data:image/jpeg;base64,${image}`;
});
</script>
</body>
</html>
//server.js
const express = require('express');
const cv = require('opencv4nodejs');
const app = express();
const path = require('path');
const FPS = 30;
const server = require('http').Server(app);
const io = require('socket.io')(server);
const wCap = new cv.VideoCapture(0);
app.get('/', function (req, res) {
res.sendFile('index.html', {root: __dirname});
});
setInterval(() => {
const frame = wCap.read();
const image = cv.imencode('.jpg', frame).toString('base64');
io.emit('image', image)
}, 1000/FPS);
server.listen(3000);

Related

How to populate the data scraped from API in node js into EJS template

My index.js file on root directory
const express = require("express");
const app = express();
const path = require("path");
const axios = require("axios").default;
const cors = require("cors");
app.set("view engine", "ejs");
app.set("views", path.join(__dirname, "/views"));
app.use(
cors({
origin: "http://localhost:3000",
})
);
fetchData = async () => {
const data = await axios.get(
"https://nepse-data-api.herokuapp.com/data/todaysprice"
);
console.log(data);
return data;
};
app.get("/", (req, res) => {
const nepseData = fetchData();
res.render("home.ejs", { nepseData });
});
app.listen(3000, () => {
console.log("listening to port 3000");
});
My home.ejs file on views directory
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>Document</title>
</head>
<body>
<%= nepseData %>
</body>
</html>
The browser is displaying this when I run the server
The API is sending this type of data
I want to show the name and prices on my ejs file. What should I do now??
You have to add await there:
app.get("/", async (req, res) => {
const nepseData = await fetchData();
res.render("home.ejs", { nepseData });
});
And then you can iterate over the data:
<% nepseData.forEach(function(row){ %>
<%= row.companyName %> <%= row.minPrice %>
<% }); %>

Why my server isn't listening the data emitted from client?

I'm learning the socket.io library in Node.js and I can't make the server receive data, only send. During tests I noticed that the io.on listener function isn't even being called, and I don't know where's my mistake. What exactly works and what doesn't is marked with commentaries in the code bellow.
My server-side code:
"use strict";
const http = require("http");
const express = require("express");
const { Server } = require("socket.io");
const { log } = console;
const app = express();
const server = http.createServer(app);
const io = new Server(server);
app.use(express.urlencoded({extended: false}));
app.use(express.json());
app.use(express.static(__dirname + "/public"));
io.on("connect", socket => {
const { id } = socket;
io.emit("receiveMsg", id); // This works
})
io.on("sendMsg", msg => { // This doesn't work
log("sendMsg: " + msg);
});
server.listen(8080);
My client-side code:
const socket = io();
const { log } = console;
socket.on("receiveMsg", msg => { // This works
log("receiveMsg: " + msg);
});
const sendMsg = () => {
const msg = document.querySelector("#msg").value;
socket.emit("sendMsg", msg); // This doesn't work
}
My client-side HTML:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Test</title>
</head>
<body>
<h1>Hello, world!</h1>
<input type="text" id="msg" placeholder="msg">
<button onclick="sendMsg()">send</button>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.3/socket.io.js"></script>
<script>
// Client-side code here
</script>
</body>
</html>
based on the doc https://socket.io/docs/v4/client-socket-instance/
the connection event is connection on server side, and connect on client side
// server-side
io.on("connection", (socket) => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});
// client-side
socket.on("connect", () => {
console.log(socket.id); // x8WIv7-mJelg7on_ALbx
});
for Emit events, if you see here https://socket.io/docs/v4/emitting-events/
it seems requires us to put the subscription event inside connection block
// server-side
io.on("connection", (socket) => {
socket.on("hello", (arg) => {
console.log(arg); // world
});
});
// client-side
socket.emit("hello", "world");
so maybe you can try to change your server code
io.on("connection", (socket) => {
socket.on("sendMsg", msg => { // This doesn't work
log("sendMsg: " + msg);
}
});
it uses socket.on, not io.on on server side

Passing variables to React compiled app from Index.html to controller.js

I'm trying to pass variables from index.html to my react app which is compiled and running on express/node server locally. I tried using the window object but node.js don't recognize the window object.
Basically once the app is loaded index.html get user info from query string and send data to userController. See code below
index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="telephone=no" name="format-detection">
<meta content="no" name="msapplication-tap-highlight">
<meta content="user-scalable=no,initial-scale=1,maximum-scale=1,minimum-scale=1,width=device-width" name="viewport">
<title>App Frontend</title>
</head>
<body>
<div id="root"></div>
<script src="js/compiledscript.js"></script>
<script>
new AppCode({
root: document.getElementById('root'),
host: 'http://localhost:3500',
endpoints: {
folder: '/api/folder',
file: '/api/file'
},
headers: {
'Content-Type': 'application/json'
}
});
//Get iframe data query from parent
function getParamValue(paramName)
{
var url = window.location.search.substring(1); //get rid of "?" in querystring
var qArray = url.split('&'); //get key-value pairs
for (var i = 0; i < qArray.length; i++)
{
var pArr = qArray[i].split('='); //split key and value
if (pArr[0] == paramName)
return pArr[1]; //return value
}
}
var userData = {
username: getParamValue('username'),
userid: getParamValue('userid')
}
window.userData = userData;
//console.log(getParamValue('username'));
//console.log(getParamValue('userid'));
</script>
</body>
</html>
userController.js
const mongoose = require('mongoose');
const path = require('path');
const fs = require('fs');
const User = mongoose.model('User');
//const users = JSON.parse(fs.readFileSync(path.join(__dirname, '..', 'data', 'users.json'), 'utf-8'));
/*
const users = window.userData;
const userid = users.userid;
exports.userid = userid;
*/
exports.getAll = async (req, res) => {
const users = await User.find();
res.json(users);
};
exports.bang = async (req, res, next) => {
await User.remove();
next();
};
exports.addNewUser = async (req, res, next) => {
await User.create(users);
// next();
};
If you are sending the HTML file as static file,
You Can do this solution:
Solution:
install ejs by running the command npm i ejs then change your file from index.html to index.ejs,
add this line to your app
app.set('view engine', 'ejs');
and send the file by
res.render('index.ejs', {
// here data to pass
});
then you can pass data to index.ejs and it will get rendered
you can read the docs in here it will clarify the image more.
if you can use server-side rendering
then redux would be the solution

Socket.IO and Express with emit data

So I trying to deposit data to user as a call made, and I have two problems.
First, when user connect its spams "user connected"
Second, I dont get any data on the page.
Here's the code:
bin/www:
var app = require('../app');
var debug = require('debug')('myapp:server');
var http = require('http');
var socketHandler = require('../handlers/sockethandler');
var io = socketHandler.io;
var server = http.createServer(app);
io.attach(server);
sockethandler.js:
var socket_io = require('socket.io');
var io = socket_io();
var socketHandler = {};
socketHandler.io = io;
io.on('connection', (socket) => {
console.log('a user connected');
socket.on('disconnect', () => {
console.log('user disconnected');
});
});
module.exports = socketHandler;
emit data post:
var socketHandler = require('./sockethandler');
var io = socketHandler.io;
var exten = evt.exten, statustext = evt.statustext;
io.emit('extenstate', {exten, statustext});
client.js:
var socket = io("http://192.168.168.49:3000");
socket.on('extenstate', function(state) {
var li = document.createElement('li');
console.log(state.exten);
var Extension = document.createElement('h4');
var Status = document.createElement('h4');
Extension.textContent = 'Extension:' + state.exten;
Status.textContent = 'Status:' + state.statustext;
li.appendChild(Extension);
li.appendChild(Status);
document.getElementById('phone-calls').appendChild(li);
});
route:
var express = require('express');
var router = express.Router();
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('data', { title: 'Realtime Sender' });
});
module.exports = router;
ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Lonestar - <%= title %></title>
</head>
<body>
<div id="phone-calls"></div>
<script src="https://cdn.socket.io/socket.io-1.3.5.js"></script>
<script src="client.js"></script>
</body>
</html>

Test express render with locals

Here is my sample code:
File: index.js
var express = required('express');
var app = express();
app.get("/", function(req, res){
...
...
res.render("/index", {
list: data
});
});
File: test.js
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('../index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function(done){
it('should render index view', function(done){
chai.request(server.app)
.get("/")
.end(function(err, res){
console.log(res.body);
});
});
});
The console.log(res.body) shows output as {}. How can I get the local list variable to show in the output? I want to test if this local list variable has any data in my test.js file.
Option 1. You should use res.json([body]) to send the list data to your test case.
E.g.
index.js:
var express = require('express');
var app = express();
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.json({ list: data });
});
module.exports = { app };
index.test.js:
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.body);
done();
});
});
});
test result:
Homepage
{ list: [ 'a', 'b' ] }
✓ should render index view
1 passing (28ms)
Option 2. You should assert the view rendered correctly with your list data.
index.js:
var express = require('express');
var path = require('path');
var app = express();
app.set('views', path.resolve(__dirname, './views'));
app.set('view engine', 'ejs');
app.get('/', function (req, res) {
const data = ['a', 'b'];
res.render('index', { list: data });
});
module.exports = { app };
views/index.ejs:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<% for (let v of list) { %>
<p><%= v %></p>
<% } %>
</body>
</html>
index.test.js:
const { expect } = require('chai');
var chai = require('chai');
var chaiHttp = require('chai-http');
var server = require('./index');
var should = chai.should();
chai.use(chaiHttp);
describe('Homepage', function (done) {
it('should render index view', function (done) {
chai
.request(server.app)
.get('/')
.end(function (err, res) {
console.log(res.text);
done();
});
});
});
test result:
Homepage
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<p>a</p>
<p>b</p>
</body>
</html>
✓ should render index view
1 passing (32ms)

Resources