How to create own Video Stream Platform using “webRTC” React with Simple-peer & socket.io & express nodejs?
create New-Folder → Inside Create Frontend-Folder & Backend-Folder.
Frontend Folder Inside Create new React-js app
npx create-react-app “name_website”
Now we should install necessary npm modules.
- npm i socket.io-client — save
socket.io use to Real time commiunication between the frontend and backend.
- npm i react-copy-to-clipboard — save
easier to text copy paste.
- npm i @material-ui/core — save
- npm i @material-ui/icons — save
material ui use web-UI styling.
+ — Now You can Copy paste App.js File to That codes. — +
import Button from “@material-ui/core/Button”;
import IconButton from “@material-ui/core/IconButton”;
import TextField from “@material-ui/core/TextField”;
import AssignmentIcon from “@material-ui/icons/Assignment”;
import PhoneIcon from “@material-ui/icons/Phone”;
import React, { useEffect, useRef, useState } from “react”;
import { CopyToClipboard } from “react-copy-to-clipboard”;
import Peer from “simple-peer”;
import io from “socket.io-client”;
import “./AudioTransmit.css”;
const socket = io.connect(‘http://localhost:5000')
const App = () => {
const [me, setMe] = useState(“”)
const [stream, setStream] = useState();
const [receivingCall, setReceivingCall] = useState(false);
const [caller, setCaller] = useState(“”);
const [callerSignal, setCallerSignal] = useState();
const [callAccepted, setCallAccepted] = useState(false);
const [idToCall, setIdToCall] = useState(“”);
const [callEnded, setCallEnded] = useState(false);
const [name, setName] = useState(“”);
const myVideo = useRef();
const userVideo = useRef();
const myAudio = useRef();
const userAudio = useRef();
const connectionRef = useRef();
useEffect(() => {
navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream) => {
setStream(stream)
myVideo.current.srcObject = stream;
myAudio.current.srcObject = stream;
})
//emit() used to send data to front end or url
/* endpoint paths in url access back end
https:/3000/me
https:/3000/disconnect
https:/3000/callUser
https:/3000/answerCall
https:/3000/callAccepted
*/
socket.on(“me”, (id) => {
setMe(id);
})
socket.on(“callUser”, (data) => {
setReceivingCall(true)
setCaller(data.from)
setName(data.name)
setCallerSignal(data.signal)
})
}, [])
const callUser = (id) => {
const peer = new Peer({
initiator: true,
trickle: false,
stream: stream
})
peer.on(“signal”, (data) => {
socket.emit(“callUser”, {
userToCall: id,
signalData: data,
from: me,
name: name
})
})
peer.on(“stream”, (stream) => {
userVideo.current.srcObject = stream;
userAudio.current.srcObject = stream;
})
socket.on(“callAccepted”, (signal) => {
setCallAccepted(true)
peer.signal(signal)
})
connectionRef.current = peer;
}
const answerCall = () => {
setCallAccepted(true)
const peer = new Peer({
initiator: false,
trickle: false,
stream: stream
})
peer.on(“signal”, (data) => {
socket.emit(“answerCall”, { signal: data, to: caller })
})
peer.on(“stream”, (stream) => {
userVideo.current.srcObject = stream;
userAudio.current.srcObject = stream;
})
peer.signal(callerSignal);
connectionRef.current = peer;
}
const leaveCall = () => {
setCallEnded(true);
connectionRef.current.destroy();
}
return (
<div>
<h1 style={{ textAlign: “center”, color: ‘#fff’ }}>savindupasingtha@gmail.com with chat</h1>
<p>1-copy uour id 2- paste your friend textbox 3- call 4- answer button click</p>
<div className=”row”>
<div className=”col-6">
<p>You</p>
{stream &&
<audio id=”myaudio” controls ref={myAudio} />
}
</div>
<div className=”col-6">
<p>Friend</p>
{callAccepted && !callEnded ?
<audio id=”friendAudio” controls ref={userAudio} />
: null}
</div>
</div>
<div className=”container”>
<div className=”video-container”>
<div className=”video”>
{stream && <video ref={myVideo} playsInline muted autoPlay controls style={{ width: “300px” }} />}
</div>
<div className=”video”>
{callAccepted && !callEnded ?
<video controls ref={userVideo} playsInline muted autoPlay controls style={{ width: “300px” }} /> :
null}
</div>
</div>
<div className=”myId”>
<TextField
id=”filled-basic”
label=”Name”
variant=”filled”
value={name}
onChange={(e) => setName(e.target.value)}
style={{ marginBottom: “20px” }}
/>
<CopyToClipboard text={me} style={{ marginBottom: “2rem” }}>
<Button variant=”contained” color=”primary” startIcon={<AssignmentIcon fontSize=”large” />}>
Copy ID
</Button>
</CopyToClipboard>
<TextField
id=”filled-basic”
label=”ID to call”
variant=”filled”
value={idToCall}
onChange={(e) => setIdToCall(e.target.value)}
/>
<div className=”call-button”>
{callAccepted && !callEnded ? (
<Button variant=”contained” color=”secondary” onClick={leaveCall}>
End Call
</Button>
) : (
<IconButton color=”primary” aria-label=”call” onClick={() => callUser(idToCall)}>
<PhoneIcon fontSize=”large” />
</IconButton>
)}
{idToCall}
</div>
</div>
<div>
{receivingCall && !callAccepted ? (
<div className=”caller”>
<h1 >{name} is calling…</h1>
<Button variant=”contained” color=”primary” onClick={answerCall}>
Answer
</Button>
</div>
) : null}
</div>
</div>
</div>
);
};
export default App;
Now App.css file to Copy this codes
.container {
display: grid;
grid-template-columns: 7fr 3fr;
}
.myId {
margin-right: 5rem;
border-radius: 5px;
background: #c9d6ff; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #e2e2e2, #c9d6ff); /* Chrome 10–25, Safari 5.1–6 */
background: linear-gradient(
to right,
#e2e2e2,
#c9d6ff
); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
padding: 2rem;
display: grid;
justify-content: center;
align-content: center;
}
.call-button {
text-align: center;
margin-top: 2rem;
}
.video-container {
display: grid;
grid-template-columns: 1fr 1fr;
justify-content: center;
align-content: center;
margin-top: 10rem;
margin-left: 10rem;
}
.caller {
text-align: center;
color: #fff;
}
body {
background: #4776e6; /* fallback for old browsers */
background: -webkit-linear-gradient(to right, #8e54e9, #4776e6); /* Chrome 10–25, Safari 5.1–6 */
background: linear-gradient(
to right,
#8e54e9,
#4776e6
); /* W3C, IE 10+/ Edge, Firefox 16+, Chrome 26+, Opera 12+, Safari 7+ */
}
Backend Folder now we can start to code.
create package.json file in the root of the tis folder.
npm install express socket.io nodemon cors http — save
- express is node js framework
- socket.io used to Real Time Data Commiunication
- cors — cross origin server Error handle
- nodemone use to server Real time run without the server close.
edit your package.json file Like this.
create a server.js file root of the back end folder.
copy paste that codes inside to the server.js file.
const express = require(“express”);
const http = require(“http”);
const app = express();
const server = http.createServer(app);
const io = require(“socket.io”)(server, {
cors: {
origin: “http://localhost:3000",
methods: [ “GET”, “POST” ]
}
});
io.on(“connection”, (socket) => {
//emit() used to send data to front end or url
/* endpoint paths in url
https:/5000/me
https:/5000/disconnect
https:/5000/callUser
https:/5000/answerCall
https:/5000/callAccepted
*/
socket.emit(“me”, socket.id);
socket.on(“disconnect”, () => {socket.broadcast.emit(“callEnded”);});
socket.on(“callUser”, (data) => {
io.to(data.userToCall).emit(“callUser”, { signal: data.signalData, from: data.from, name: data.name });
})
socket.on(“answerCall”, (data) => {
io.to(data.to).emit(“callAccepted”, data.signal)
})
})
server.listen(5000, () => console.log(“server is running on port 5000”))
Now you can run your App.
Run React App — npm start
Back end run — node server.js