How to send and receive desktop capture stream gen

2019-02-21 05:25发布

问题:

I am making a Screen sharing app with WebRTC + Socket.io and stuck at a place. Connected with two browser using WebRTC + Socket.io and can send text

I am taking support from codelab but it is not for stream.(If solution is based on this link then highly helpful)

How can I send getUserMedia() stream:

dataChannel.send(stream);

And receive same stream on channel.onmessage(): I am getting event.data as '[object MediaStream]' not stream.

channel.onmessage = function(event){
  // unable to get correct stream
  // event.data is "[object MediaStream]"  in string
}

function createPeerConnection(isInitiator, config) {
    console.log('Creating Peer connection as initiator?', isInitiator, 'config:', config);
    peerConn = new RTCPeerConnection(config);

    // send any ice candidates to the other peer
    peerConn.onicecandidate = function (event) {
        console.log('onIceCandidate event:', event);
        if (event.candidate) {
            sendMessage({
                type: 'candidate',
                label: event.candidate.sdpMLineIndex,
                id: event.candidate.sdpMid,
                candidate: event.candidate.candidate
            });
        } else {
            console.log('End of candidates.');
        }
    };

    if (isInitiator) {
        console.log('Creating Data Channel');
        dataChannel = peerConn.createDataChannel("screen");
        onDataChannelCreated(dataChannel);

        console.log('Creating an offer');
        peerConn.createOffer(onLocalSessionCreated, logError);
    } else {
        peerConn.ondatachannel = function (event) {
            console.log('ondatachannel:', event.channel);
            dataChannel = event.channel;
            onDataChannelCreated(dataChannel);
        };
    }
}

It is working fine for string or json i.e. dataChannel.send('Hello');

I have created a wiki page for same: wiki

Please help.

回答1:

Please try something like this: (explanation at the end of the code)

var btnShareYourCamera = document.querySelector('#share-your-camera');
var localVideo = document.querySelector('#local-video');
var remoteVideo = document.querySelector('#remote-video');

var websocket = new WebSocket('wss://path-to-server:port/');
websocket.onmessage = function(event) {
    var data = JSON.parse(event.data);
    if (data.sdp) {
        if (data.sdp.type === 'offer') {
            getUserMedia(function(video_stream) {
                localVideo.srcObject = video_stream;
                answererPeer(new RTCSessionDescription(data.sdp), video_stream);
            });
        }

        if (data.sdp.type === 'answer') {
            offerer.setRemoteDescription(new RTCSessionDescription(data.sdp));
        }
    }

    if (data.candidate) {
        addIceCandidate((offerer || answerer), new RTCIceCandidate(data.candidate));
    }
};

var iceTransportPolicy = 'all';
var iceTransportLimitation = 'udp';

function addIceCandidate(peer, candidate) {
    if (iceTransportLimitation === 'tcp') {
        if (candidate.candidate.toLowerCase().indexOf('tcp') === -1) {
            return; // ignore UDP
        }
    }

    peer.addIceCandidate(candidate);
}

var offerer, answerer;

var iceServers = {
    iceServers: [{
        'urls': [
            'stun:stun.l.google.com:19302',
            'stun:stun1.l.google.com:19302',
            'stun:stun2.l.google.com:19302',
            'stun:stun.l.google.com:19302?transport=udp',
        ]
    }],
    iceTransportPolicy: iceTransportPolicy,
    rtcpMuxPolicy: 'require',
    bundlePolicy: 'max-bundle'
};

// https://https;//cdn.webrtc-experiment.com/IceServersHandler.js
if (typeof IceServersHandler !== 'undefined') {
    iceServers.iceServers = IceServersHandler.getIceServers();
}

var mediaConstraints = {
    OfferToReceiveAudio: true,
    OfferToReceiveVideo: true
};

/* offerer */

function offererPeer(video_stream) {
    offerer = new RTCPeerConnection(iceServers);
    offerer.idx = 1;

    video_stream.getTracks().forEach(function(track) {
        offerer.addTrack(track, video_stream);
    });

    offerer.ontrack = function(event) {
        remoteVideo.srcObject = event.streams[0];
    };

    offerer.onicecandidate = function(event) {
        if (!event || !event.candidate) return;
        websocket.send(JSON.stringify({
            candidate: event.candidate
        }));
    };

    offerer.createOffer(mediaConstraints).then(function(offer) {
        offerer.setLocalDescription(offer).then(function() {
            websocket.send(JSON.stringify({
                sdp: offer
            }));
        });
    });
}

/* answerer */

function answererPeer(offer, video_stream) {
    answerer = new RTCPeerConnection(iceServers);
    answerer.idx = 2;

    video_stream.getTracks().forEach(function(track) {
        answerer.addTrack(track, video_stream);
    });

    answerer.ontrack = function(event) {
        remoteVideo.srcObject = event.streams[0];
    };

    answerer.onicecandidate = function(event) {
        if (!event || !event.candidate) return;
        websocket.send(JSON.stringify({
            candidate: event.candidate
        }));
    };

    answerer.setRemoteDescription(offer).then(function() {
        answerer.createAnswer(mediaConstraints).then(function(answer) {
            answerer.setLocalDescription(answer).then(function() {
                websocket.send(JSON.stringify({
                    sdp: answer
                }));
            });
        });
    });
}

var video_constraints = {
    mandatory: {},
    optional: []
};

function getUserMedia(successCallback) {
    function errorCallback(e) {
        alert(JSON.stringify(e, null, '\t'));
    }

    var mediaConstraints = {
        video: true,
        audio: true
    };

    navigator.mediaDevices.getUserMedia(mediaConstraints).then(successCallback).catch(errorCallback);
}

btnShareYourCamera.onclick = function() {
    getUserMedia(function(video_stream) {
        localVideo.srcObject = video_stream;
        offererPeer(video_stream);
    });
};
  1. You must attach stream using peer.addTrack as you can see in the above example
  2. You must receive remote stream using peer.ontrack as you can see in the above example

i.e. use addTrack to attach your camera and use ontrack to receive remote camera.

You must never send your stream using dataChannel.send. Both are totally different protocols. A MediaStream must be shared using RTP; not SCTP. RTP is used only if you call peer.addTrack method to attach your camera stream.

This process happens before you open or join a room.

See single-page demo here: https://www.webrtc-experiment.com/getStats/

HTML for above code snippet:

<button id="share-your-camera"></button>
<video id="local-video" controls autoplay playsinline></video>
<video id="remote-video" controls autoplay playsinline></video>