Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

WebRTC: Switch camera

Tags:

webrtc

I want to be able to switch the camera while in the middle of a conversation with WebRTC, without renegotiating the call.

Suppose we have 2 "mediaSources" objects using the MediaStreamTrack.getSources method:

{
    id: "id_source_1" | "id_source_2",
    facing: "user" | "environment",
    kind: "kind_1" | "kind_2",
    label: "label_1" | "label_2"
 }

We start the call with "source_1" (facing the "user"), and we want the user to be able to switch to "source_2" (facing the "environment").

In my current code when the user clicks the "switch camera" button the following is executed: (callingSession is the current WebRTC session)

var mediaParams = {
       audio: true,
       video: { deviceId : source_2.id},
       options: {
           muted: true,
           mirror: true
       },
       elemId: 'localVideo'
};

callingSession.getUserMedia(mediaParams, function (error, stream) {
if (error) {
   console.error('error getting user media');
} else {
          var oldVideoTracks = callingSession.localStream.getVideoTracks();      
          var newVideoTracks = stream.getVideoTracks();

          if (oldVideoTracks.length > 0 && newVideoTracks.length > 0) {
               callingSession.localStream.removeTrack(oldVideoTracks[0]);
               callingSession.localStream.addTrack(newVideoTracks[0]);
          } 
       }
 });

As you can see the mediaParams constraints is now set to the "source_2", we pass this mediaParams with new constraints to the getUserMedia method. Then we get the video tracks from both the old and the new stream.

The main problem in this code, is that the old stream is still exactly the same as the new stream, even with the new constraints passed to the getUserMedia method, so obviously the same video tracks, and of course nothing happens, and the camera is not switched !!!

Am I doing something wrong in this code ? is there any way to switch the camera without without renegotiating the call in WebRTC ? what about the experimental method applyConstraint() I am not able to see it in chrome ?

Thank you.

UPDATE My WebRTC app is an ionic app with crosswalk => the webview is chrome

like image 483
dafriskymonkey Avatar asked Aug 24 '16 14:08

dafriskymonkey


1 Answers

At the time of writing this post, the WebRTC specification is very promising but still the implementation of this specification varies from browser to another. Currently the Chrome implementation is still old. Nevertheless thanks to jib comments and to this SO answer and also more understanding of the SDP (Session Description Protocol) I can now switch the camera using Chrome.

First the constraints to my getUserMedia method were wrong, here is how I managed to pass the right constraints :

var mediaParams = {
            // the other constraints
            video: {mandatory: {sourceId: source_2.id}}
            // ...
        };

After calling getUserMedia with the mediaParams argument we need to remove the current stream from the peer connection then add the new one like this :

peerConnection.removeStream(peerConnection.getLocalStreams()[0]);
peerConnection.addLocalStream(stream);

Those two lines of code will trigger the onnegotiationneeded on the peerConnection object, means peer 1 must tell peer 2 he changed the stream so he needs a new description. Thats why we need to create an offer, set the new description and send this new description to the peer :

peerConnection.createOffer()
.then(function (offer) {
      peerConnection.setLocalDescription(offer);
})
.then(function () {
      send(JSON.stringify({ "sdp": peerConnection.localDescription }));
});

At this point its up to you how you want to send the SDP. (In my use case I had to send them using WebSockets.)

Once the other peer receives the new SDP he must set it in his own peer connection :

var obj = JSON.parse(answer).sdp;
peerConnection.setRemoteDescription(new RTCSessionDescription(obj));

I hope this will help someone someday.

like image 155
dafriskymonkey Avatar answered Dec 19 '22 02:12

dafriskymonkey