Step 1: install filrebase SDK
npm install firebase
Step 2 : Configure Firebase
import firebase from 'firebase/app';
import 'firebase/firestore';
const firebaseConfig = {
apiKey: "YOUR_API_KEY",
authDomain: "YOUR_PROJECT_ID.firebaseapp.com",
projectId: "YOUR_PROJECT_ID",
storageBucket: "YOUR_PROJECT_ID.appspot.com",
messagingSenderId: "YOUR_MESSAGING_SENDER_ID",
appId: "YOUR_APP_ID"
};
firebase.initializeApp(firebaseConfig);
const firestore = firebase.firestore();
export { firestore };
Step 3 : Set Up WebRTC
import { firestore } from './firebase';
const servers = {
iceServers: [
{
urls: 'stun:stun.l.google.com:19302'
}
],
iceCandidatePoolSize: 10
};
let pc = new RTCPeerConnection(servers);
let localStream = null;
let remoteStream = null;
export const initWebRTC = async (localVideoRef, remoteVideoRef) => {
localStream = await navigator.mediaDevices.getUserMedia({ video: true, audio: true });
remoteStream = new MediaStream();
localStream.getTracks().forEach(track => {
pc.addTrack(track, localStream);
});
pc.ontrack = event => {
event.streams[0].getTracks().forEach(track => {
remoteStream.addTrack(track);
});
};
localVideoRef.current.srcObject = localStream;
remoteVideoRef.current.srcObject = remoteStream;
};
export const createOffer = async () => {
const callDoc = firestore.collection('calls').doc();
const offerCandidates = callDoc.collection('offerCandidates');
const answerCandidates = callDoc.collection('answerCandidates');
pc.onicecandidate = event => {
event.candidate && offerCandidates.add(event.candidate.toJSON());
};
const offerDescription = await pc.createOffer();
await pc.setLocalDescription(offerDescription);
const offer = {
sdp: offerDescription.sdp,
type: offerDescription.type
};
await callDoc.set({ offer });
callDoc.onSnapshot(snapshot => {
const data = snapshot.data();
if (!pc.currentRemoteDescription && data?.answer) {
const answerDescription = new RTCSessionDescription(data.answer);
pc.setRemoteDescription(answerDescription);
}
});
answerCandidates.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type === 'added') {
const candidate = new RTCIceCandidate(change.doc.data());
pc.addIceCandidate(candidate);
}
});
});
return callDoc.id;
};
export const answerCall = async (callId) => {
const callDoc = firestore.collection('calls').doc(callId);
const offerCandidates = callDoc.collection('offerCandidates');
const answerCandidates = callDoc.collection('answerCandidates');
pc.onicecandidate = event => {
event.candidate && answerCandidates.add(event.candidate.toJSON());
};
const callData = (await callDoc.get()).data();
const offerDescription = callData.offer;
await pc.setRemoteDescription(new RTCSessionDescription(offerDescription));
const answerDescription = await pc.createAnswer();
await pc.setLocalDescription(answerDescription);
const answer = {
type: answerDescription.type,
sdp: answerDescription.sdp
};
await callDoc.update({ answer });
offerCandidates.onSnapshot(snapshot => {
snapshot.docChanges().forEach(change => {
if (change.type === 'added') {
const candidate = new RTCIceCandidate(change.doc.data());
pc.addIceCandidate(candidate);
}
});
});
};
Step 4 : Create React Components VideoCall.js
import React, { useRef } from 'react';
import { initWebRTC, createOffer, answerCall } from './webrtc';
const VideoCall = () => {
const localVideoRef = useRef(null);
const remoteVideoRef = useRef(null);
const callIdRef = useRef(null);
const startCall = async () => {
await initWebRTC(localVideoRef, remoteVideoRef);
const callId = await createOffer();
callIdRef.current.value = callId;
};
const joinCall = async () => {
const callId = callIdRef.current.value;
await initWebRTC(localVideoRef, remoteVideoRef);
await answerCall(callId);
};
return (
<div>
<div>
<video ref={localVideoRef} autoPlay playsInline></video>
<video ref={remoteVideoRef} autoPlay playsInline></video>
</div>
<input ref={callIdRef} type="text" placeholder="Enter Call ID" />
<button onClick={startCall}>Start Call</button>
<button onClick={joinCall}>Join Call</button>
</div>
);
};
export default VideoCall;
STep 5 : Integrate with Your App
import React from 'react';
import VideoCall from './VideoCall';
function App() {
return (
<div className="App">
<header className="App-header">
<h1>React Video Call with Firebase</h1>
</header>
<VideoCall />
</div>
);
}
export default App;