Below is my node-js WebRTC server and im wondering how I can make it as fast as possible. Things i’ve done so far is in the OBS virtual camera lower my resolution down as much as possible and lower the framerate to 30. The server is being run with node-js and im using a TURN server for clients being behind NAT’s.
server.js
const express = require("express");
const http = require("http");
const socketIo = require("socket.io");
const app = express();
const server = http.createServer(app);
const io = socketIo(server);
let broadcaster;
const port = 4000;
io.sockets.on("error", (e) => console.log(e));
io.sockets.on("connection", (socket) => {
console.log("A user connected:", socket.id, socket.handshake.address);
socket.on("broadcaster", () => {
broadcaster = socket.id;
socket.broadcast.emit("broadcaster");
console.log(socket.id, "is broadcasting");
});
socket.on("watcher", () => {
console.log(socket.id, "is watching");
socket.to(broadcaster).emit("watcher", socket.id);
});
socket.on("offer", (id, message) => {
socket.to(id).emit("offer", socket.id, message);
console.log(socket.id, "sent an offer to", id);
});
socket.on("answer", (id, message) => {
socket.to(id).emit("answer", socket.id, message);
console.log(socket.id, "sent an answer to", id);
});
socket.on("candidate", (id, message) => {
socket.to(id).emit("candidate", socket.id, message);
console.log(socket.id, "sent a candidate to", id);
});
socket.on("disconnect", () => {
console.log("A user disconnected:", socket.id);
socket.to(broadcaster).emit("disconnectPeer", socket.id);
});
});
server.listen(port, "0.0.0.0", () =>
console.log(`Server is running on http://0.0.0.0:${port}`)
);
broadcast.html
<!DOCTYPE html>
<html>
<head>
<title>Broadcaster</title>
<meta charset="UTF-8" />
</head>
<body>
<video playsinline autoplay muted></video>
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js"></script>
<script>
const peerConnections = {};
const config = {
iceServers: [
],
};
const socket = io.connect('http://:4000');
socket.on("answer", (id, description) => {
peerConnections[id].setRemoteDescription(description);
});
socket.on("watcher", id => {
const peerConnection = new RTCPeerConnection(config);
peerConnections[id] = peerConnection;
let stream = videoElement.srcObject;
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit("candidate", id, event.candidate);
}
};
peerConnection
.createOffer()
.then(sdp => peerConnection.setLocalDescription(sdp))
.then(() => {
socket.emit("offer", id, peerConnection.localDescription);
});
});
socket.on("candidate", (id, candidate) => {
peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate));
});
socket.on("disconnectPeer", id => {
peerConnections[id].close();
delete peerConnections[id];
});
window.onunload = window.onbeforeunload = () => {
socket.close();
};
// Get camera stream
const videoElement = document.querySelector("video");
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
videoElement.srcObject = stream;
socket.emit("broadcaster");
})
.catch(error => console.error("Error: ", error));
</script>
</body>
</html>
watch.html
<!DOCTYPE html>
<html>
<head>
<title>Broadcaster</title>
<meta charset="UTF-8" />
</head>
<body>
<video playsinline autoplay muted></video>
<script src="https://cdn.jsdelivr.net/npm/socket.io-client@4/dist/socket.io.js"></script>
<script>
const peerConnections = {};
const config = {
iceServers: [
,
],
};
const socket = io.connect('http://:4000');
socket.on("answer", (id, description) => {
peerConnections[id].setRemoteDescription(description);
});
socket.on("watcher", id => {
const peerConnection = new RTCPeerConnection(config);
peerConnections[id] = peerConnection;
let stream = videoElement.srcObject;
stream.getTracks().forEach(track => peerConnection.addTrack(track, stream));
peerConnection.onicecandidate = event => {
if (event.candidate) {
socket.emit("candidate", id, event.candidate);
}
};
peerConnection
.createOffer()
.then(sdp => peerConnection.setLocalDescription(sdp))
.then(() => {
socket.emit("offer", id, peerConnection.localDescription);
});
});
socket.on("candidate", (id, candidate) => {
peerConnections[id].addIceCandidate(new RTCIceCandidate(candidate));
});
socket.on("disconnectPeer", id => {
peerConnections[id].close();
delete peerConnections[id];
});
window.onunload = window.onbeforeunload = () => {
socket.close();
};
// Get camera stream
const videoElement = document.querySelector("video");
navigator.mediaDevices.getUserMedia({ video: true })
.then(stream => {
videoElement.srcObject = stream;
socket.emit("broadcaster");
})
.catch(error => console.error("Error: ", error));
</script>
</body>
</html>