I am trying to figure out how to change the microphone or webcam while you are in a videochat with someone.
I have been now trying for a few days and nothing works. I was following this example, but it seems it is much harder to achieve the change while someone is already connected.
The issues I have: If I change the mic the sound is lost/the mic doesnt react at all. I also cannot change it back to the default.
A similar thing happens if I change the webcam. The stream hangs, the last frame is seen.
I get no error message, in fact it tells me that the changes were successful.
Changing the webcam/mic WORKS before the call is established
Here is the relevant codeblock. Everywhere I am reading just create new constraints and give the desired deviceId to the audio/video stream.:
function ChangeDevice() { if (localStream) { localStream.getTracks().forEach(track => { track.stop(); }); } var audioSource = audioInputSelect.value; var videoSource = videoSelect.value; console.log(videoSource); console.log(audioSource); const newConstraints = { audio: {deviceId: audioSource ? {exact: audioSource} : undefined}, video: {deviceId: videoSource ? {exact: videoSource} : undefined} }; navigator.mediaDevices.getUserMedia(newConstraints).then(gotStream).then(gotDevices).catch(handleError); } function gotStream(stream) { console.log('Adding local stream.'); localStream = stream; localVideo.srcObject = stream; sendMessage(['got user media', room]); if (isInitiator) { maybeStart(); } return navigator.mediaDevices.enumerateDevices(); // I added this }
I think these two are the relevant functions, ChangeDevice is called when I select a new device from a dropdown. The id’s are correct.
Here is the whole code I use:
Advertisement
Answer
Luckily replaceTrack
seems to work now on all browsers, so there is no need to renegotiate.
I had to edit my gotStream
function like this:
function gotStream(stream) { // If already started // Need this if webcam or mic changes if (isStarted) { var videoTrack = stream.getVideoTracks()[0]; var audioTrack = stream.getAudioTracks()[0]; var sender = pc.getSenders().find(function(s) { return s.track.kind == videoTrack.kind; }); var sender2 = pc.getSenders().find(function(s) { return s.track.kind == audioTrack.kind; }); console.log('found sender:', sender); sender.replaceTrack(videoTrack); sender2.replaceTrack(audioTrack); localStream = stream; localVideo.srcObject = stream; } else { console.log('Adding local stream.'); localStream = stream; localVideo.srcObject = stream; sendMessage(['got user media', room]); if (isInitiator) { maybeStart(); } } return navigator.mediaDevices.enumerateDevices(); // I added this }