Your Web News in One Place

Help Webnuz

Referal links:

Sign up for GreenGeeks web hosting
June 13, 2021 05:54 pm GMT

Create simple voice chat app with nodejs

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 expressconst 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="https://dev.to/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;}

Alt Text

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.


Original Link: https://dev.to/hosseinmobarakian/create-simple-voice-chat-app-with-nodejs-1b70

Share this article:    Share on Facebook
View Full Article

Dev To

An online community for sharing and discovering great ideas, having debates, and making friends

More About this Source Visit Dev To