Ask coding questions

← Back to all posts
How can I make an application sort of like facetime with javascript?
TSelden (5)

A repl is attached to this (I think) that has my code in it. Everything works fine, no errors, but it either won't broadcast or recieve. I'm not sure why, but please don't judge me as I'm new to the javascript camera. I know how websockets work, and I've made many successful projects with them, too. So can anybody help me with this? Thanks in advance!

Commentshotnewtop
SpicedSpices (255)

The way to make something like that is through using websockets like Socket.IO. I have made quite a few multiplayer games and webapps using Socket.IO and I find it very helpful to use. It is way too much to explain in one comment so if you want to watch a 45 minute long youtube video I created one on how to use Socket.IO lol.

But the basics are pretty much this code:

It will have to be created in a Node.JS file so you can download NPM packages.

This is the code to setup the server:

const express = require("express");
const app = express();
const serv = require("http").Server(app);

app.get('/', function(req, res){
  res.sendFile(__dirname + "/client/index.html");
  console.log("express connection");
});
app.use("/client", express.static(__dirname + "/client"));

serv.listen(8000);
console.log("server started");

The code to setup socket.io is this:

const io = require("socket.io")(serv, {});

io.sockets.on("connection", function(socket){
socket.emit("data", {
a: "random string or something"
}
});

You will also need to setup a client side so create a folder called client, add an index.html file into that folder, and also add a script.js file in there.

The index.html file should look like this:

<DOCTYPE! html>
<html>
<head>
  <meta charset="utf-8">
  <title>idk some title or something</title>
</head>
<body>
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
<script src="client/script.js"></script>
</body>
</html>

After that in your script.js file add this code:

const socket = io();
socket.on('data', (data) => {
console.log(data.a);
});

If you are confused, don't worry so was I when I started learning this. If you want to watch the video, heres the link: https://www.youtube.com/watch?v=e17Lv35Tm-8
Also if you want me to help you create something like this just reply to this and I might join your repl or something.

I hope this helped :)

TSelden (5)

@SpicedSpices Okay, I'll check it out! Quick question, though: Is it free?

TSelden (5)

@SpicedSpices Okay, I'll check it out! Quick question, though: Is it free?

SpicedSpices (255)

@TSelden yeah socket.io and all other npm packages are totally free

SpicedSpices (255)

@TSelden do you need help setting things up?

TSelden (5)

@SpicedSpices No, I'm good for now, but if I need any help with it, I'll just reply to this and It will give you a notification.

TSelden (5)

@SpicedSpices Sort of:

var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('test', (socket) => {
  socket.broadcast.emit('broadcast', 'hello friends!');
});

http.listen(3674, () => {
  console.log('listening on *:3674');
});

I'm honestly very confused. I'm used to using raw websocket connections (I use websocket.in), and I'm not sure what all this means. So here are my questions:
1) What does io.on do and what triggers it?
2) What does http.listen do and what triggers it?
3) How can I receive messages?
Sorry, I'm just new to all this, and I would appreciate it if you answered these. Thanks in advance!

SpicedSpices (255)

@TSelden

1) io.on is triggered whenever the first parameter (in your case 'test') is triggered. You have 'test' in there which is not a valid parameter. For something to happen, you need to have some other parameter, the main one is 'connection' which will trigger whenever there is a connection to the socket.

io.on('connection', (socket) => {
  socket.broadcast.emit('broadcast', 'hello friends!')
});

That will send emit something to the person connected saying 'hello friends'

2) What http.listen does it listens to a certain port. There are thousands of ports to choose from but the main ones are in the 3000s and the 8000s, you already have that set up. Whenever a request is sent to the server through port 3674, the http will pick that up, send it to the io.on, and it will take the response from io.on and send it back to the client. Repl.It already deals with sending requests on the same port though, so you don't need to configure that on the client side.

3) To receive requests from the server, you need to first have the socket.io script in your html
<script src="https://cdn.socket.io/socket.io-1.4.5.js"></script>
After that, you will need to configure socket.io in your script.js or whatever other script that you have, and its easily called as
const socket = io()
From there, you can use socket to receive requests from the server. It is a simple socket.on([whatever the server sent], and then dealing with the data in a function. If you sent the data to the client through what you did, you will only need a single parameter for the function

socket.on('broadcast', a => {
  console.log(a)
})

But if you have multiple things being sent to the client, such as socket.broadcast.emit('broadcast', 'hello friends!', 1, 432, 'dfhrj3'), you can easily get that through multiple parameters, or if you have a multitude of data to send to the client, you can put it into a JSON object and take one parameter on the client end.

socket.broadcast.emit('broadcast', {
  str: 'hello friends!'
  code: 6802
});

Client:

socket.on('broadcast', data => {
  console.log(data.str, data.code);
}

If you are trying to receive data from the client, you can send data from the client using socket.emit('name', 40284), and you can receive data from the client by using

socket.on('name', str => { console.log(str) })

inside of your

io.on('connection', (socket) => {

})
TSelden (5)

@SpicedSpices Okay, so here's what I've got so far:
index.html:

<!doctype html>
<html>
  <head>
    <title>Socket.IO chat</title>
    <style>
      * { margin: 0; padding: 0; box-sizing: border-box; }
      body { font: 13px Helvetica, Arial; }
      form { background: #000; padding: 3px; position: fixed; bottom: 0; width: 100%; }
      form input { border: 0; padding: 10px; width: 90%; margin-right: 0.5%; }
      form button { width: 9%; background: rgb(130, 224, 255); border: none; padding: 10px; }
      #messages { list-style-type: none; margin: 0; padding: 0; }
      #messages li { padding: 5px 10px; }
      #messages li:nth-child(odd) { background: #eee; }
    </style>
  </head>
  <body>
    <ul id="messages"></ul>
    <form action="">
      <input id="m" autocomplete="off" /><button>Send</button>



      <script src="/socket.io/socket.io.js"></script>
<script src="https://code.jquery.com/jquery-3.4.1.min.js"></script>
<script>
var socket = io();
var video = document.createElement('video');
video.setAttribute('playsinline', '');
video.setAttribute('autoplay', '');
video.setAttribute('muted', 'true');
video.style.width = screenX + 'px;';
video.style.height = screenY + 'px;';
document.body.appendChild(video);
var video2 = document.createElement('video');
video2.setAttribute('playsinline', '');
video2.setAttribute('autoplay', '');
video2.setAttribute('muted', 'true');
video2.style.width = screenX + 'px;';
video2.style.height = screenY + 'px;';
document.body.appendChild(video2);

var facingMode = "user";
var constraints = {
  audio: true,
  video: {
   facingMode: facingMode
  }
};
var s;
streamloop();
function streamloop() {
  navigator.mediaDevices.getUserMedia(constraints).then(function success(stream) {
  video.srcObject = stream;
  s = toString(stream);
  socket.emit('stream', s);
});
requestAnimationFrame(streamloop)
}

socket.on('stream', function(msg){
      video2.srcObject = msg;
    });
</script>



    </form>
  </body>
</html>

index.js (node.js server):

var app = require('express')();
var http = require('http').createServer(app);
var io = require('socket.io')(http);

app.get('/', (req, res) => {
  res.sendFile(__dirname + '/index.html');
});

io.on('connection', (socket) => {
  console.log('a user connected');
  socket.on('disconnect', () => {
    console.log('user disconnected');
  });
});

http.listen(3674, () => {
  console.log('listening on *:3674');
});

io.on('connection', (socket) => {
  socket.on('stream', (msg) => {
    io.emit(msg);
  });
});

Doesn't seem to be working too well, any advice?

SpicedSpices (255)

@TSelden in your index.js file you only need 1 io.on('connection'), you can put the other stuff inside of your first io.on('connection')

Also, what doesn't seem to be working correctly?

TSelden (5)

@SpicedSpices First of all, I know it's sending and recieving the messages, but it won't show up in video2. Second, in the window where you can see yourself, it's flashing on and off like crazy. I'm pretty sure this is a result of the requestanimationframe in streamloop(). Here's a link to the repl: Node-1. Thanks!

TSelden (5)

Also: I do not like using APIs, libraries, or frameworks (websockets are okay, though). Don't ask why.

brandosha (12)

I've made something similar if you want to check out my code
https://repl.it/@brandosha/webrtc

TSelden (5)

@brandosha Thanks, I'll check it out!