Reputation: 11
I'm developing a WebRTC application, and I'm encountering an error related to setting the remote description and creating an answer. I'm using the WebRTC API, and when I attempt to set the remote description for the answer, I'm getting the following error:``
Expected Behavior: I expected to set the local stream and remote stream on the client screen, but currently only the local stream is displayed.
import React, { useCallback, useEffect, useState } from "react";
import { useSocket } from "../providers/Socket";
import { usePeer } from "../providers/Peer";
const RoomPage = () => {
const { socket } = useSocket();
const { peer } = usePeer();
const {
createOffer,
createAnswer,
setRemoteAns,
sendStream,
remoteStream,
setRemoteStream,
} = usePeer();
const [myStream, setMyStream] = useState(null);
const [remoteEmailId, setRemoteEmailId] = useState(null);
const handleNewUserJoined = useCallback(
async (data) => {
const { emailId } = data;
console.log("New user joined room : ", emailId);
const offer = await createOffer();
socket.emit("call-user", { emailId, offer });
setRemoteEmailId(emailId);
},
[createOffer, socket]
);
const handleIncomingCall = useCallback(
async (data) => {
const { from, offer } = data;
console.log("Incoming call from ", from, offer);
const ans = await createAnswer(offer);
socket.emit("call-accepted", { emailId: from, ans });
setRemoteEmailId(from);
},
[createAnswer, socket]
);
const handleCallAccepted = useCallback(
async (data) => {
const { ans } = data;
console.log("Call got accepted: ", ans);
if (peer) {
try {
await setRemoteAns(ans); // Set the remote answer
} catch (error) {
console.error("Error setting remote description (answer):", error);
}
}
},
[peer, setRemoteAns]
);
const getUserMediaStream = useCallback(async () => {
try {
const stream = await navigator.mediaDevices.getUserMedia({
audio: true,
video: true,
});
setMyStream(stream);
setRemoteStream(remoteStream);
} catch (error) {
console.error("Error accessing user media:", error);
}
}, []);
const handleNegotiation = useCallback(async () => {
const localOffer = peer.localDescription;
socket.emit("call-user", { emailId: remoteEmailId, offer: localOffer });
}, [peer.localDescription, remoteEmailId, socket]);
useEffect(() => {
socket.on("user-joined", handleNewUserJoined);
socket.on("incoming-call", handleIncomingCall);
socket.on("call-accepted", handleCallAccepted);
return () => {
socket.off("user-joined", handleNewUserJoined);
socket.off("incoming-call", handleIncomingCall);
socket.off("call-accepted", handleCallAccepted);
};
}, []);
useEffect(() => {
peer.addEventListener("negotiationneeded", handleNegotiation);
return () => {
peer.removeEventListener("negotiationneeded", handleNegotiation);
};
}, [handleNegotiation]);
useEffect(() => {
getUserMediaStream();
}, [getUserMediaStream]);
const handleSendVideo = () => {
console.log("Sending video stream...");
sendStream(myStream);
};
return (
<div className="room-page-container">
<h1>Room Page</h1>
<h4>You are connected to {remoteEmailId}</h4>
<button onClick={handleSendVideo}>Send my Video</button>
{myStream && (
<video
autoPlay
playsInline
muted
ref={(videoRef) => {
if (videoRef) {
videoRef.srcObject = myStream;
}
}}
></video>
)}
{remoteStream && (
<video
autoPlay
playsInline
ref={(videoRef) => {
if (videoRef) {
videoRef.srcObject = remoteStream;
}
}}
></video>
)}
</div>
);
};
export default RoomPage;
import React, { useMemo, useState, useCallback, useEffect } from "react";
const PeerContext = React.createContext(null);
export const usePeer = () => React.useContext(PeerContext);
export const PeerProvider = (props) => {
const [peer, setPeer] = useState(null);
const [remoteStream, setRemoteStream] = useState(null);
useEffect(() => {
const initPeer = async () => {
const rtcPeer = new RTCPeerConnection({
iceServers: [
{
urls: [
"stun:stun.l.google.com:19302",
"stun:global.stun.twilio.com:3478",
],
},
],
});
setPeer(rtcPeer);
};
initPeer();
}, []);
const handleTrackEvent = useCallback((ev) => {
const streams = ev.streams;
setRemoteStream(streams[0]);
}, []);
useEffect(() => {
if (peer) {
peer.addEventListener("track", handleTrackEvent);
return () => {
peer.removeEventListener("track", handleTrackEvent);
};
}
}, [handleTrackEvent, peer]);
const createOffer = useCallback(async () => {
if (peer) {
const offer = await peer.createOffer();
await peer.setLocalDescription(offer);
return offer;
}
return null;
}, [peer]);
const createAnswer = async (offer) => {
if (peer) {
try {
await peer.setRemoteDescription(offer); // Set the remote offer
const answer = await peer.createAnswer();
await peer.setLocalDescription(answer); // Set the local answer
return answer;
} catch (error) {
console.error("Error creating answer:", error);
return null;
}
}
return null;
};
const setRemoteAns = async (ans) => {
if (peer) {
try {
await peer.setRemoteDescription(ans); // Set the remote answer
} catch (error) {
console.error("Error setting remote description (answer):", error);
}
}
};
const sendStream = async (stream) => {
if (peer) {
const tracks = stream.getTracks();
tracks.forEach((track) => {
if (!peer.getSenders().some((sender) => sender.track === track)) {
peer.addTrack(track, stream);
}
});
}
};
return (
<PeerContext.Provider
value={{
peer,
createOffer,
createAnswer,
setRemoteAns,
sendStream,
remoteStream,
setRemoteStream,
}}
>
{props.children}
</PeerContext.Provider>
);
};
Additional Information:
My application runs on a localhost server (http://localhost:3000). I'm using the Socket.IO library for real-time communication. I'm using the WebRTC API for establishing peer connections.
Question:
What is causing these errors related to setting the remote description and creating an answer in my WebRTC application? How can I resolve these errors and successfully set the remote description and create an answer? Any insights or suggestions on how to address these issues would be greatly appreciated. Thank you!
Upvotes: 1
Views: 94