3

So I was following this tutorial to learn how to implement a WebRTC server-client setup. Once I got that working I wanted to split the client into two parts, one sender and one receiver. Now they can establish a connection with each other but the receiver never gets the stream from the sender.

I managed to determine that the code flow between the original code and split versions remains the same, except that neither peer executes the onicecandidate event.

According to this I need to explicitly include OfferToReceiveAudio: true and OfferToReceiveVideo: true since I'm using Chrome, which I did but it didn't seem to make any difference.

Currently, they both receive SDP from each other, there is a local and remote description in the peerConnection, and iceGatheringState is "new" but iceConnectionState is "checking" (unlike the second link where he states it should also be "new")

How come they aren't exchanging ICE candidates when it's split in two like this?

Sender.js

const HTTPSPort = 3434;
const domain = '127.0.0.1';
const wssHost = 'wss://' + domain + ':' + HTTPSPort + '/websocket/';

// Feed settings
const video = true;
const audio = true;
const constraints = { "audio": audio, "video": video };

var videoContainer = null, feed = null,
 pC = null, wsc = new WebSocket(wssHost),
 pCConfig = [
  { 'url': 'stun:stun.services.mozilla.com' },
  { 'url': 'stun:stun.l.google.com:19302' }
 ];

function pageReady() {
 // Check browser WebRTC availability
 navigator.mediaDevices.getUserMedia(constraints).then(function (stream) {
  videoContainer = document.getElementById('videoFeed');

  // Get the feed and show it in the local video element
  feed = stream;
  videoContainer.srcObject = feed;
 }).catch(function () {
  alert("Sorry, your browser does not support WebRTC!");
 });
}

wsc.onmessage = function (evt) {
 if (!pC) {
  // Initiate peerConnection
  pC = new RTCPeerConnection(pCConfig);

  // Send any ice candidates to the other peer
  pC.onicecandidate = onIceCandidateHandler;

  pC.addStream(feed);
 }

 // Read the message
 var signal = JSON.parse(evt.data);
 if (signal.sdp) {
  log('Received SDP from remote peer.');
  pC.setRemoteDescription(new RTCSessionDescription(signal.sdp));

  answerCall();
 } else if (signal.candidate) {
  log('Received ICECandidate from remote peer.');
  pC.addIceCandidate(new RTCIceCandidate(signal.candidate));
 }
};

function answerCall() {
 pC.createAnswer().then(function (answer) {
  var ans = new RTCSessionDescription(answer);
  pC.setLocalDescription(ans).then(function () {
   wsc.send(JSON.stringify({ 'sdp': ans }));
  }).catch(errorHandler);
 }).catch(errorHandler);
}

function onIceCandidateHandler(evt) {
 if (!evt || !evt.candidate) return;

 wsc.send(JSON.stringify({ 'candidate': evt.candidate }));
};

Receiver.js

const HTTPSPort = 3434;
const domain = '127.0.0.1';
const wssHost = 'wss://' + domain + ':' + HTTPSPort + '/websocket/';

var remoteVideo = null,
 pC = null, wsc = new WebSocket(wssHost),
 pCConfig = [
  { 'url': 'stun:stun.services.mozilla.com' },
  { 'url': 'stun:stun.l.google.com:19302' }
 ],
 mediaConstraints = {
  mandatory: {
   OfferToReceiveAudio: true,
   OfferToReceiveVideo: true
  }
 };

function pageReady() {
 remoteVideo = document.getElementById('remoteVideo');
 icebutton = document.getElementById('checkICE');
 icebutton.addEventListener('click', function (evt) {
  console.log(pC);
 })
};

wsc.onopen = function () {
 // Initiates peerConnection
 pC = new RTCPeerConnection(pCConfig);

 // Send any ICE candidates to the other peer
 pC.onicecandidate = onIceCandidateHandler;

 // Once remote stream arrives, show it in the remote video element
 pC.onaddstream = onAddStreamHandler;

 // Offer a connection to the server
 createAndSendOffer();
};

function createAndSendOffer() {
 pC.createOffer(mediaConstraints).then(function (offer) {
  var off = new RTCSessionDescription(offer);
  pC.setLocalDescription(off).then(function () {
   wsc.send(JSON.stringify({ 'sdp': off }));
  }).catch(errorHandler);
 }).catch(errorHandler);
}

wsc.onmessage = function (evt) {
 // Read the message
 var signal = JSON.parse(evt.data);

 if (signal.sdp) {
  console.log('Received SDP from remote peer.');
  pC.setRemoteDescription(new RTCSessionDescription(signal.sdp));
 } else if (signal.candidate) {
  console.log('Received ICECandidate from remote peer.');
  pC.addIceCandidate(new RTCIceCandidate(signal.candidate));
 }
};

function onIceCandidateHandler(evt) {
 if (!evt || !evt.candidate) return;

 wsc.send(JSON.stringify({ 'candidate': evt.candidate }));
};

function onAddStreamHandler(evt) {
 // Set remote video stream as source for remote video HTML element
 remoteVideo.srcObject = evt.stream;
};
Community
  • 1
  • 1
Jabos
  • 45
  • 6

1 Answers1

5

You forgot iceServers. Change

pCConfig = [
    { 'url': 'stun:stun.services.mozilla.com' },
    { 'url': 'stun:stun.l.google.com:19302' }
];

to

pCConfig = {
    iceServers: [
        { urls: 'stun:stun.l.google.com:19302' }
    ]
};

Additionally:

Tips

Kudos for using promises (unlike the tutorial)! Note you can return them to flatten things:

function createAndSendOffer() {
    return pC.createOffer(mediaConstraints).then(function (offer) {
        return pC.setLocalDescription(offer);
    })
    .then(function () {
        wsc.send(JSON.stringify({ sdp: pC.localDescription }));
    })
    .catch(errorHandler);
}
Community
  • 1
  • 1
jib
  • 40,579
  • 17
  • 100
  • 158
  • 1
    Thank you very much, it solved my issue. I could have sworn that I got an error that told me to remove `iceServers`, which is why I did... Also, thank you for going through the effort of telling me about everything that has been depricated, "sourced" even. – Jabos May 15 '17 at 18:53