I am currently working for WebRTC multipeer connection. I want to implement feature to switch camera from front to back while on call. This is the code I am using to switch cameras
async function changevideo() {
const audioSource = audioInputSelect.value;
const videoSource = videoSelect.options[videoSelect.selectedIndex].value;
var tempconstraints ={
video: {
deviceId: videoSource ? { exact: videoSource } : undefined,
width: { max: 320 },
height: { max: 240 }
},
audio: { deviceId: audioSource ? { exact: audioSource } : undefined },
};
var newstream = await navigator.mediaDevices.getUserMedia(tempconstraints);
if (connections[socketId]) {
Promise.all(connections[socketId].getSenders().map(function (sender) {
debugger;
return sender.replaceTrack(newstream.getTracks().find(function (track) {
debugger;
return track.kind === sender.track.kind;
})).then(data =>
{
console.log(data);
});;
}));
var track = localStream.getTracks().find(function (track) { return track.kind == videoTrack.kind });
localStream.removeTrack(track);
localStream.addTrack(videoTrack);
connections[tempsocketid].onnegotiationneeded = function () {
connections[tempsocketid].createOffer().then(function (offer) {
return connections[tempsocketid].setLocalDescription(offer);
}).then(function () {
socket.emit('signal', socketId, JSON.stringify({ 'sdp': connections[tempsocketid].localDescription, 'room': roomNumber }), roomNumber);
}).catch(e => console.log(e));
}
}
}
Here connections contains the RTCpeerconnection details of all type of connections connected.
socketId
is the id of main user on which I want to switch camera. So, connections[socketId]
gives me the RTCPeerConnection details of user with socketId.
newstream
is the stream after switching camera.
If I directly update src of video to newstream then my camera changes only on my device.
I have searched alot but everywhere I am getting solution to use replaceTrack
but it is not wokring in my case. Everytime I use it nothing happens on screen and I am also not getting any error in console.
Update
I have used the onnegotiationneeded
with remove and add track.
tempsocketid
is the socketId of another user who is connected.
So I have 2 users one have socketid stored in socketId
and another having socketid stored in tempsocketid
. So currently I am trying to switch camera of user with socketid socketId
and when negotiation is called then I am getting error in another users console.
DOMException: Failed to execute 'addIceCandidate' on 'RTCPeerConnection': Error processing ICE candidate
I have fixed the issue the problem was with socketId I was sending socketId of current user with different user.
As replace track was not working so I have used removeTrack
and addTrack
to force negotiation.
Here is my working code
if (connections[socketId]) {
localStream.getVideoTracks()[0].enabled = false;
var track = localStream.getTracks().find(function (track) { return track.kind == videoTrack.kind });
localStream.removeTrack(track);
localStream.addTrack(videoTrack);
connections[tempsocketid].onnegotiationneeded = function () {
console.log('negotiationstarted');
connections[tempsocketid].createOffer().then(function (offer) {
return connections[tempsocketid].setLocalDescription(offer);
}).then(function () {
console.log('negotiation signal sent');
socket.emit('signal', tempsocketid, JSON.stringify({ 'sdp': connections[tempsocketid].localDescription, 'room': roomNumber }), roomNumber);
}).catch(e => console.log(e));
}
localStream.getVideoTracks()[0].enabled = true;
}