This content originally appeared on DEV Community and was authored by h_mobarakian
Hi, I'm Hossein in this article we will build a simple voice chat web application with nodejs and socketIo.
In the first step, we will create a simple interface for our app. To did that we use handlebars.
Before starting coding we must install dependencies, run commands below:
npm init -y
npm i express socket.io express-handlebars
After installing dependencies, create and open index.js file and put codes below into it:
const express = require("express");
const app = express();
const handlebars = require("express-handlebars");
const http = require("http").Server(app);
const io = require("socket.io")(http);
//To holding users information
const socketsStatus = {};
//config and set handlebars to express
const customHandlebars = handlebars.create({ layoutsDir: "./views" });
app.engine("handlebars", customHandlebars.engine);
app.set("view engine", "handlebars");
//enable user access to public folder
app.use("/files", express.static("public"));
app.get("/home" , (req , res)=>{
res.render("index");
});
http.listen(3000, () => {
console.log("the app is run in port 3000!");
});
Now we jump into handlebars files first create main.handlebars in 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>Hossein Mobarakian - voice chat application</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/socket.io/4.1.2/socket.io.js" integrity="sha512-iZIBSs+gDyTH0ZhUem9eQ1t4DcEn2B9lHxfRMeGQhyNdSUz+rb+5A3ummX6DQTOIs1XK0gOteOg/LPtSo9VJ+w==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
</head>
<body>
{{{body}}}
</body>
</html>
Note: main.handlebars is the base template in handlebars and you can change it in config your handlebars setting.
In this step we can go to create index.handlebars in the views directory.
<header>
<div class="user-controller">
<p id="username-label"></p>
<div id="username-div">
<input type="text" id="username">
<button class="username-btn" onclick="changeUsername()">Change username</button>
</div>
</div>
<div class="controller">
<button class="control-btn disable-btn" onclick="toggleMicrophone(this)">Open microphone</button>
<button class="control-btn disable-btn" onclick="toggleMute(this)">Mute</button>
<button class="control-btn disable-btn" onclick="toggleConnection(this)">Go online</button>
</div>
</header>
<h2>users list</h2>
<ul class="users" id="users">
</ul>
<script src="/files/js/index.js"></script>
<link rel="stylesheet" href="/files/css/index.css">
Add some style to our interface with create index.css in /public/css/ folder.
html , body {
width: 100%;
height: 100%;
overflow: hidden;
}
.controller{
margin: 0;
padding: 0;
overflow: hidden;
display: flex;
justify-content: center;
}
body{
display: flex;
text-align: center;
flex-flow: column;
margin: 0;
padding: 0;
background-color: rgb(12 11 25);
color: #fff;
}
header{
margin:0;
padding: 20px 0;
width: 100%;
height: fit-content;
background-color: rgb(15, 15, 44);
color: #fff;
}
.control-btn{
width: 120px;
padding: 10px 0;
border: none;
border-radius: 8px;
cursor: pointer;
}
.enable-btn{
background-color: rgb(26, 184, 26);
color: #fff;
border-bottom: 5px solid rgb(18, 131, 18);
margin: 10px ;
}
.enable-btn:hover{
border-bottom: none;
margin-top: 15px;
}
.disable-btn{
margin: 10px ;
background-color: rgb(172, 25, 25);
color: #fff;
border-bottom: 5px solid rgb(184, 57, 57);
}
.disable-btn:hover{
border-bottom: none;
margin-top: 15px;
}
.username-btn{
width: 200px;
margin: 10px auto;
padding: 10px 0;
}
input{
width: 200px;
padding: 10px;
margin: 10px auto;
}
#username-div{
display: none;
}
#username-label{
width: 200px;
height: fit-content;
margin: 0 auto;
padding: 10px 20px;
background-color: rgb(12 11 25);
border-radius: 8px;
border: 2px solid rgb(26, 26, 77);
cursor: pointer;
}
ul.users{
width: 100%;
margin: 0;
padding: 0;
}
ul.users li{
width: 90%;
margin: 10px auto;
padding: 10px 0;
text-align: center;
background-color: rgb(15 15 44);
list-style: none;
color: #fff;
border-radius: 8px;
}
In the last part of this project, we use socket to make our app in realtime.Now put socket codes into index.js above the http.listen(...):
io.on("connection", function (socket) {
const socketId = socket.id;
socketsStatus[socket.id] = {};
console.log("connect");
socket.on("voice", function (data) {
var newData = data.split(";");
newData[0] = "data:audio/ogg;";
newData = newData[0] + newData[1];
for (const id in socketsStatus) {
if (id != socketId && !socketsStatus[id].mute && socketsStatus[id].online)
socket.broadcast.to(id).emit("send", newData);
}
});
socket.on("userInformation", function (data) {
socketsStatus[socketId] = data;
io.sockets.emit("usersUpdate",socketsStatus);
});
socket.on("disconnect", function () {
delete socketsStatus[socketId];
});
});
After that create a front-end javascript file in /public/js/index.js and put codes below into it:
const userStatus = {
microphone: false,
mute: false,
username: "user#" + Math.floor(Math.random() * 999999),
online: false,
};
const usernameInput = document.getElementById("username");
const usernameLabel = document.getElementById("username-label");
const usernameDiv = document.getElementById("username-div");
const usersDiv = document.getElementById("users");
usernameInput.value = userStatus.username;
usernameLabel.innerText = userStatus.username;
window.onload = (e) => {
mainFunction(1000);
};
var socket = io("ws://localhost:3000");
socket.emit("userInformation", userStatus);
function mainFunction(time) {
navigator.mediaDevices.getUserMedia({ audio: true }).then((stream) => {
var madiaRecorder = new MediaRecorder(stream);
madiaRecorder.start();
var audioChunks = [];
madiaRecorder.addEventListener("dataavailable", function (event) {
audioChunks.push(event.data);
});
madiaRecorder.addEventListener("stop", function () {
var audioBlob = new Blob(audioChunks);
audioChunks = [];
var fileReader = new FileReader();
fileReader.readAsDataURL(audioBlob);
fileReader.onloadend = function () {
if (!userStatus.microphone || !userStatus.online) return;
var base64String = fileReader.result;
socket.emit("voice", base64String);
};
madiaRecorder.start();
setTimeout(function () {
madiaRecorder.stop();
}, time);
});
setTimeout(function () {
madiaRecorder.stop();
}, time);
});
socket.on("send", function (data) {
var audio = new Audio(data);
audio.play();
});
socket.on("usersUpdate", function (data) {
usersDiv.innerHTML = '';
for (const key in data) {
if (!Object.hasOwnProperty.call(data, key)) continue;
const element = data[key];
const li = document.createElement("li");
li.innerText = element.username;
usersDiv.append(li);
}
});
}
usernameLabel.onclick = function () {
usernameDiv.style.display = "block";
usernameLabel.style.display = "none";
}
function changeUsername() {
userStatus.username = usernameInput.value;
usernameLabel.innerText = userStatus.username;
usernameDiv.style.display = "none";
usernameLabel.style.display = "block";
emitUserInformation();
}
function toggleConnection(e) {
userStatus.online = !userStatus.online;
editButtonClass(e, userStatus.online);
emitUserInformation();
}
function toggleMute(e) {
userStatus.mute = !userStatus.mute;
editButtonClass(e, userStatus.mute);
emitUserInformation();
}
function toggleMicrophone(e) {
userStatus.microphone = !userStatus.microphone;
editButtonClass(e, userStatus.microphone);
emitUserInformation();
}
function editButtonClass(target, bool) {
const classList = target.classList;
classList.remove("enable-btn");
classList.remove("disable-btn");
if (bool)
return classList.add("enable-btn");
classList.add("disable-btn");
}
function emitUserInformation() {
socket.emit("userInformation", userStatus);
}
run command:
node index.js
Congratulation! Now you have a realtime voice chat app created with nodejs and socketIo.I hope useful this article to you and thank you to read it.
This content originally appeared on DEV Community and was authored by h_mobarakian
h_mobarakian | Sciencx (2021-06-13T17:54:48+00:00) Create simple voice chat app with nodejs. Retrieved from https://www.scien.cx/2021/06/13/create-simple-voice-chat-app-with-nodejs/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.