Reputation: 41
I am working on a new website. You can join room calls and make a voicecall so use your webcam but you can also share your screen.
The problem is when i add the track to the stream the peer doesn't work more... I don't know how to solve this. I also tried to change the code from adding the track to adding a new stream or anything else but cannot find a solution. Can anyone help me?
Client:
export default function Meeting(props) {
const userVideo = useRef();
const partnerVideo = useRef();
const screenShare = useRef();
const peerRef = useRef();
const socketRef = useRef();
const otherUser = useRef();
const userStream = useRef();
const userScreen = useRef();
useEffect(() => {
navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(stream => {
userVideo.current.srcObject = stream;
userStream.current = stream;
socketRef.current = socketIOClient.connect(ENDPOINT);
socketRef.current.emit("join room", props.room);
socketRef.current.on('other user', userID => {
callUser(userID);
otherUser.current = userID;
});
socketRef.current.on("user joined", userID => {
otherUser.current = userID;
});
socketRef.current.on("offer", handleRecieveCall);
socketRef.current.on("answer", handleAnswer);
socketRef.current.on("ice-candidate", handleNewICECandidateMsg);
});
}, []);
function callUser(userID) {
console.log("call user - - -d-s-d-s-d--sd-sdd-sd-ssd-sd-sd--");
peerRef.current = createPeer(userID);
userStream.current.getTracks().forEach(track => peerRef.current.addTrack(track, userStream.current));
}
function createPeer(userID) {
const peer = new RTCPeerConnection({
//sdpSemantics: 'unified-plan',
iceServers: [
{
urls: "stun:stun.stunprotocol.org"
},
{
urls: 'turn:numb.viagenie.ca',
credential: 'muazkh',
username: '[email protected]'
},
]
});
peer.onicecandidate = handleICECandidateEvent;
peer.ontrack = handleTrackEvent;
peer.onnegotiationneeded = () => {
if (peer.signalingState != "stable") return;
handleNegotiationNeededEvent(userID);
}
return peer;
}
function handleNegotiationNeededEvent(userID) {
console.log("negotiationsad-das-d-as-d-asd--asd-a-sd-a-sd-");
peerRef.current.createOffer().then(offer => {
return peerRef.current.setLocalDescription(offer);
}).then(() => {
const payload = {
target: userID,
type: "video-offer",
caller: socketRef.current.id,
sdp: peerRef.current.localDescription
};
socketRef.current.emit("offer", payload);
}).catch(e => console.log(e));
}
function handleRecieveCall(incoming) {
peerRef.current = createPeer();
const desc = new RTCSessionDescription(incoming.sdp);
peerRef.current.setRemoteDescription(desc).then(() => {
userStream.current.getTracks().forEach(track => peerRef.current.addTrack(track, userStream.current));
}).then(() => {
return peerRef.current.createAnswer();
}).then(answer => {
return peerRef.current.setLocalDescription(answer);
}).then(() => {
const payload = {
target: incoming.caller,
type: "video-offer",
caller: socketRef.current.id,
sdp: peerRef.current.localDescription
}
socketRef.current.emit("answer", payload);
})
}
function handleAnswer(message) {
const desc = new RTCSessionDescription(message.sdp);
peerRef.current.setRemoteDescription(desc).catch(e => console.log(e));
}
function handleICECandidateEvent(e) {
if (e.candidate) {
const payload = {
target: otherUser.current,
candidate: e.candidate,
}
socketRef.current.emit("ice-candidate", payload);
}
}
function handleNewICECandidateMsg(incoming) {
const candidate = new RTCIceCandidate(incoming);
if (peerRef.current && candidate) {
peerRef.current.addIceCandidate(candidate).catch(e => console.log(e));
}
}
function handleTrackEvent(e) {
var stream = e.streams[0];
var tracks = stream.getTracks();
var lun = tracks.length;
console.log(tracks);
if (lun === 2) {
partnerVideo.current.srcObject = stream;
} else if (lun === 1) {
screenShare.current.srcObject = stream;
}
};
function shareScreen() {
navigator.mediaDevices.getDisplayMedia({ cursor: true }).then(stream => {
screenShare.current.srcObject = stream;
userScreen.current = stream;
const screenTrack = stream.getTracks()[0];
callUser(otherUser.current);
peerRef.current.addTrack(screenTrack, stream);
screenTrack.onended = function () {
peerRef.current.removeTrack(screenTrack);
}
})
}
return (
<div>
<video controls style={{ height: 500, width: 500 }} autoPlay ref={userVideo} />
<video controls style={{ height: 500, width: 500 }} autoPlay ref={partnerVideo} />
<video controls style={{ height: 500, width: 500 }} autoPlay ref={screenShare} />
<button onClick={shareScreen}>Share screen</button>
</div>
);
};
Upvotes: 3
Views: 1174
Reputation: 42430
In shareScreen
you're adding a second track to the existing peer connection with addTrack
, which triggers renegotiation (causes your onnegotiationneeded
handler to run again). This is correct so far, and triggers a second offer/answer exchange, which is needed for media track additions.
You're just not set up to handle renegotiation correctly, because you've mixed initialization code in with your (re)negotiation code, causing a new RTCPeerConnection
object to be created when you already have one.
Renegotiation is going to happen whenever you add tracks or stop their underlying transceivers, so you don't want initialization code in your negotiation code. Instead do this:
Move the creation of your RTCPeerConnection
out of handleReceiveCall
. Create it on page load instead.
Move the addition of tracks out of handleReceiveCall
as well if you can, or at least skip re-adding them if they've already been added.
Your ontrack
is going to fire again with the screen-sharing track, so you need to add code to handle that. You can differentiate it from the camera track by event.streams[0].id
and event.transceiver.mid
being different, or simply from this being the third track.
Upvotes: 1