Jabos
Jabos

Reputation: 45

Not receiving video, onicecandidate is not executing

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;
};

Upvotes: 3

Views: 1240

Answers (1)

jib
jib

Reputation: 42450

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);
}

Upvotes: 5

Related Questions