WebRTC flow of function calls for making calls [An

2020-05-29 07:21发布

I am referring and also going through source code of AppRTCDemo which is a demo application for WebRTC.

What i am trying is:

  1. Build my own WebRTC application which will do AV calls on a Android Device.
  2. Replace existing https://apprtc.appspot.com/ server and related functionality.

For archiving above points, I want to understand basic flow of WebRTC function calls and steps to make/receive calls (functions that i need to calls and there flow).

I have gone through the source code and understood few things, but as code is pretty complicated to understand, and without any documentation.

It will be great help if some one provides any examples or documents explaining the steps for making/receiving AV calls (how we get/set SDP, how to render local/remote video etc.).

I have seen these posts and are very helpful:

  1. WebRTC java server trouble
  2. https://www.webrtc-experiment.com/docs/WebRTC-PeerConnection.html

I am able to build and run AppRTCDemo App.

Any help on this will be great help!

1条回答
Melony?
2楼-- · 2020-05-29 07:43

There is no timeline, it's asynchronous but i will try to explain but there is two main flow, the flow of offer and answer with SDP and the flow of icecandidate.

Flow 1 : SDP

Step 1 - Offer peer :

On the offer side, create a RTCPeerconnection (with stun, trun servers as parameters).

    var STUN = {
        url:'stun:stun.l.google.com:19302'
    };

    var TURN = {
        url: 'turn:homeo@turn.bistri.com:80',
        credential: 'homeo'
    };

    var iceServers = {
        iceServers: [STUN, TURN]
    };

    var peer = new RTCPeerConnection(iceServers);

Step 2 - Offer peer :

Call getUserMedia with your constraints. In the success callback, add the stream to the RTCPeerconnection using the addStream method. Then you can create the offer with calling createOffer on the Peerconnection Object.

    navigator.webkitGetUserMedia(
    {
      audio: false,
      video: {
        mandatory: {
          maxWidth: screen.width,
          maxHeight: screen.height,
          minFrameRate: 1,
          maxFrameRate: 25
        }
      }
    },
    gotStream, function(e){console.log("getUserMedia error: ", e);});

    function gotStream(stream){
      //If you want too see your own camera
      vid.src = webkitURL.createObjectURL(stream);

      peer.addStream(stream);

      peer.createOffer(onSdpSuccess, onSdpError);
    }

Step 3 - Offer peer :

In the callback method of the createOffer, set the parameter (the sdp offer) as the localDescription of the RTCPeerConnection (who will start gathering the ICE candidate). Then send the offer to the other peer using the signaling server. (I will not describe signaling server, it's just passing data to one from another).

    function onSdpSuccess(sdp) {
        console.log(sdp);
        peer.setLocalDescription(sdp);
        //I use socket.io for my signaling server
        socket.emit('offer',sdp);
    }

Step 5 - Answer peer :

The answer peer, each time it receives an offer, create a RTCPeerconnection with TURN, STUN server, then getUserMedia, then in the callback, add the stream to the RTCPeerConnection. With the SDP offer use setRemoteDescription with the sdpOffer. Then Trigger the createAnswer. In the success callback of the createAnswer, use setLocalDescription with the parameter and then send the answer sdp to the offer peer using signaling server.

    //Receive by a socket.io socket
    //The callbacks are useless unless for tracking
    socket.on('offer', function (sdp) {
        peer.setRemoteDescription(new RTCSessionDescription(sdp), onSdpSuccess, onSdpError);

        peer.createAnswer(function (sdp) {
            peer.setLocalDescription(sdp);
            socket.emit('answer',sdp);
        }, onSdpError);

    }); 

Step 7 : Offer peer

Receive the sdp answer, setRemoteDescription on the RTCPeerConnection.

    socket.on('answer', function (sdp) {
      peer.setRemoteDescription(new RTCSessionDescription(sdp), function(){console.log("Remote Description Success")}, function(){console.log("Remote Description Error")});
    }); 

Flow 2 : ICECandidate

Both side :

Each time the RTCPeerConnection fire onicecandidate, send the candidate to the other peer through signalingserver. When a icecandidate is received, coming from signaling server, just add it to the RTCPeerConnection using the addIceCandidate(New RTCIceCandidate(obj))

    peer.onicecandidate = function (event) {
      console.log("New Candidate");
      console.log(event.candidate);

      socket.emit('candidate',event.candidate);
    };

    socket.on('candidate', function (candidate) {
      console.log("New Remote Candidate");
      console.log(candidate);

      peer.addIceCandidate(new RTCIceCandidate({
          sdpMLineIndex: candidate.sdpMLineIndex,
          candidate: candidate.candidate
      }));
    }); 

Finally :

If two flow above works well use the onaddstream event on each RTCPeerConnection. When ICE Candidates will pair each other and find the best way for peer-to-peer, they will add the stream negociated with the SDP and that is going through the peer to peer connection. So in this event, you juste need to add your stream then to a video tag for example and it's good.

    peer.onaddstream = function (event) {
      vid.src = webkitURL.createObjectURL(event.stream);
      console.log("New Stream");
      console.log(event.stream);
    };

I will edit tommorow with some code i think to help understand what i'm saying. If have question go for it.

Here is my signaling server :

var app = require('express')();
var server = require('http').Server(app);
var io = require('socket.io')(server);

server.listen(3000);

app.get('/', function (req, res) {
  res.send('The cake is a lie');
});

io.on('connection', function (socket) {

  console.log('NEW CONNECTION');

  socket.on('offer', function (data) {
    console.log(data);
    socket.broadcast.emit("offer",data);
  });

  socket.on('answer', function (data) {
    console.log(data);
    socket.broadcast.emit("answer",data);
  });

  socket.on('candidate', function (data) {
    console.log(data);
    socket.broadcast.emit("candidate",data);
  });

});

查看更多
登录 后发表回答