1

I am trying to implement share screen function in webrtc video conferencing. From suggestion, I am now following muaz-khan's solution using https://www.webrtc-experiment.com/getScreenId/ . I can easily capture the application images of one peer, and replace the video stream with the capture stream. But it is a video conferencing experiment, so two browsers need to video conference with each other. For example, browser 1, has video streams A (local video), video streams B (remote video); browser 2 has video streams B (local video), video streams A (remote video). So when I am in browser 1 and trying to share the screen, the share screen stream should replace the local video in browser 1, and remote video in browser 2.

But right now, I can only make the share screen replace the local video in browser 1, browser 2 doesn't have any changes, cann't see any changes in its remote video (which is the local video in browser 1). I don't know how to trigger the changes in browser 2 as well. do i need to signal the share screen streams to server? and change the remote stream accordingly?

Here is my code in javascript:

$(function() {
    var brokerController, ws, webRTC, localid; 
    // ws = new XSockets.WebSocket("wss://rtcplaygrouund.azurewebsites.net:443", ["connectionbroker"], {
    ws = new XSockets.WebSocket("ws://localhost:4502", ["connectionbroker"], {
        ctx: "152300ed-4d84-4e72-bc99-965052dc1e95"
    }); 

    var addRemoteVideo = function(peerId,mediaStream) {
        var remoteVideo = document.createElement("video");
        remoteVideo.setAttribute("autoplay", "true");
        remoteVideo.setAttribute("rel",peerId);
        attachMediaStream(remoteVideo, mediaStream);                       
        remoteVideo.setAttribute("class", "col-md-3");
        remoteVideo.setAttribute("height", $( document ).height() * 0.3);
        remoteVideo.setAttribute("id", 'remoteVideo');                      
        $("#videoscreen").append(remoteVideo);
    };

    var onConnectionLost = function (remotePeer) {
        console.log("onconnectionlost");
        var peerId = remotePeer.PeerId;
        var videoToRemove = $("video[rel='" + peerId + "']");
        videoToRemove.remove();
    };

    var oncConnectionCreated = function() {
        console.log("oncconnectioncreated", arguments);
    }

    var onGetUerMedia = function(stream) {
    console.log("Successfully got some userMedia , hopefully a goat will appear..");
    webRTC.connectToContext(); // connect to the current context?
    };

    var onRemoteStream = function (remotePeer) {      
    addRemoteVideo(remotePeer.PeerId, remotePeer.stream);
    console.log("Opps, we got a remote stream. lets see if its a goat..");

    };

    var onLocalStream = function(mediaStream) {
    console.log("Got a localStream", mediaStream.id);
    localid = mediaStream.id;
    console.log("check this id:  meadiastram id ", mediaStream.id);

    var video = document.createElement("video");
    video.setAttribute("height", "100%");
    video.setAttribute("autoplay", "true");
    video.setAttribute("id", "localvideo");
    video.setAttribute("name", mediaStream.id);

    attachMediaStream(video, mediaStream);                  
    $("#videoscreen").append(video);

    $('#share').click(function() {

        getScreenId(function (error, sourceId, screen_constraints) {

            navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
            navigator.getUserMedia(screen_constraints, function (stream) {
                $('#localvideo').attr('src', URL.createObjectURL(stream));                     

            }, function (error) {
                console.error(error);
                });
            });
        });

    };

    var onContextCreated = function(ctx) {
    console.log("RTC object created, and a context is created - ", ctx);
    webRTC.getUserMedia(webRTC.userMediaConstraints.hd(true), onGetUerMedia, onError);
    };

    var onOpen = function() {
        console.log("Connected to the brokerController - 'connectionBroker'");

        webRTC = new XSockets.WebRTC(this);
        webRTC.onlocalstream = onLocalStream;
        webRTC.oncontextcreated = onContextCreated;
        webRTC.onconnectioncreated = oncConnectionCreated;
        webRTC.onconnectionlost = onConnectionLost;       
        webRTC.onremotestream = onRemoteStream;
    };

    var onConnected = function() {
        console.log("connection to the 'broker' server is established");
        console.log("Try get the broker controller form server..");
        brokerController = ws.controller("connectionbroker");
        brokerController.onopen = onOpen;

    };              
    ws.onconnected = onConnected;

}); 

I am using xsocket as the server, and the codes for click share and change the local stream with the share screen streams are just very simple as this:

$('#share').click(function() {
    getScreenId(function (error, sourceId, screen_constraints) {
        navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
        navigator.getUserMedia(screen_constraints, function (stream) {
            $('#localvideo').attr('src', URL.createObjectURL(stream));

        }, function (error) {
               console.error(error);
           });
    });

Any help or suggestion would be grateful.

Thanks for pointing out the other post: How to addTrack in MediaStream in WebRTC, but I don't think they are the same. And also I am not sure how to renegotiate the remote connection in this case.

Xsocket.webrtc.js file for webrtc connection: https://github.com/XSockets/XSockets.WebRTC/blob/master/src/js/XSockets.WebRTC.latest.js

How I could I renegotiate the remote connection in this case?

Community
  • 1
  • 1
Pengzhi Zhou
  • 481
  • 1
  • 6
  • 24
  • 1
    Possible duplicate of [How to addTrack in MediaStream in WebRTC](http://stackoverflow.com/questions/35504214/how-to-addtrack-in-mediastream-in-webrtc) – jib Jun 03 '16 at 17:53
  • If you're using Firefox, you can also use [replaceTrack](http://stackoverflow.com/a/32465439/918910). – jib Jun 03 '16 at 17:58
  • @jib, Thanks for pointing out the other post: How to addTrack in MediaStream in WebRTC, it seems like that could help, but not sure they are the same yet, as using renegotiation can help refresh the remote stream in Browser 2.. So do you mean when share application in local stream of browser 1, then trigger a command to server, and notify back browser 2, to update its remote stream (which = the local stream in browser 1). But in this case, in browser 2, the remote stream is still using the old getusermedia configuration. Since I just update the source in local stream, nothing more. – Pengzhi Zhou Jun 04 '16 at 23:35
  • Remote streams don't come from *getUserMedia*, they come from *RTCPeerConnection*. You have to switch which stream you're sending to the other side. How to do that varies between browsers unfortunately, as the other answer mentions. – jib Jun 06 '16 at 16:47
  • @jib, from the post you send to me, is using pc.onnegotiationneeded from remote stream in browser 2, do I understand correctly? Since in my code, I am using a warp xsocket webrtc javascript file for making connection, could you explain more how I can do the renegotiation for remote stream? I have attached the key xsocket webrtc code in my original post. thanks. – Pengzhi Zhou Jun 07 '16 at 08:03
  • @jib, for the xsocket.webrtc.js file: github.com/XSockets/XSockets.WebRTC/blob/master/src/js/…, how I can do the renegotiate in this case? . Currently, I am trying to send a command to the server, and get it back in the remote stream browser, and try to refresh the stream with negotiation, but can't get it done. Errors happening. And I am using chrome only. – Pengzhi Zhou Jun 07 '16 at 09:25
  • *pc.onnegotiationneeded* is on sender side (both ends really). I don't have insight or time to debug your specific case, but I've updated [my answer in the duplicate question](http://stackoverflow.com/a/35515536/918910) to include a working renegotiation over data-channel demo. Hope that helps! – jib Jun 07 '16 at 19:24

2 Answers2

1

I figured out a work around solution by myself for this question, do not replace the local stream with the sharescreen stream, instead remove the old local stream from local div, then add the new sharescreen stream to local div. In the meantime, send the old local stream id by datachanel to the other peer, and remove that old remote video as well.

The most important thing is reflesh the streams (renegotiation), then sharescreen stream would display in remote peer.

Code:

$('#share').click(function() {
    getScreenId(function (error, sourceId, screen_constraints) {
        navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
        navigator.getUserMedia(screen_constraints, function (stream) {
            webRTC.removeStream(webRTC.getLocalStreams()[0]);
            var id = $('#localvideo').attr('name');
            $('#localvideo').remove();
            brokerController.invoke('updateremotevideo', id);
            webRTC.addLocalStream(stream);
            webRTC.getRemotePeers().forEach(function (p) {
                webRTC.refreshStreams(p);
            });
        }, function (error) {
               console.error(error);
           });
   });            
}); 

after get the command to remove that old video stream from the server:

brokerController.on('updateremotevideo', function(streamid){
    $(document.getElementById(streamid)).remove();
});

This solution works for me. Although if only like to replace the local video stream with share screen stream, we need to re create the offer with sdp, and send sdp to remote peer. It is more complicated.

Usman Maqbool
  • 3,351
  • 10
  • 31
  • 48
Pengzhi Zhou
  • 481
  • 1
  • 6
  • 24
0
 getScreenId(function (error, sourceId, screen_constraints) {
  navigator.getUserMedia = navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
  navigator.getUserMedia(screen_constraints, function (stream) {
    navigator.getUserMedia({audio: true}, function (audioStream) {
      stream.addTrack(audioStream.getAudioTracks()[0]);
      var mediaRecorder = new MediaStreamRecorder(stream);
      mediaRecorder.mimeType = 'video/mp4'
      mediaRecorder.stream = stream;
      self.setState({recorder: mediaRecorder, startRecord: true,  shareVideo: true, pauseRecord: false, resumeRecord: false, stopRecord: false, downloadRecord: false, updateRecord: false});
      document.querySelector('video').src = URL.createObjectURL(stream);
      var video =  document.getElementById('screen-video')
      if (video) {
        video.src = URL.createObjectURL(stream);
        video.width = 360;
        video.height = 300;
      }
    }, function (error) {
      alert(error);
    });
  }, function (error) {
    alert(error);
  });
});