I have signaling server in java and websocket.
It works well with local video. but Remote video is black screen or blank
But it is not always a blank. If you turn off the server and turn it on again, the remote video will show up on your remote.
Why does not it always come out sometimes, and sometimes it does not come out?
this is my code...
navigator.getUserMedia = navigator.getUserMedia || navigator.mozGetUserMedia || navigator.webkitGetUserMedia;
window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
window.RTCIceCandidate = window.RTCIceCandidate || window.mozRTCIceCandidate || window.webkitRTCIceCandidate;
window.RTCSessionDescription = window.RTCSessionDescription || window.mozRTCSessionDescription || window.webkitRTCSessionDescription;
window.SpeechRecognition = window.SpeechRecognition || window.webkitSpeechRecognition || window.mozSpeechRecognition
|| window.msSpeechRecognition || window.oSpeechRecognition;
var localVideoStream = null;
var peerConn = null,
wsc = new WebSocket("ws://localhost:8080/signaling"),
peerConnCfg = {
'iceServers': [{
'url': 'stun:stun.l.google.com:19302'
}]
};
var videoCallButton = document.getElementById("caller");
var endCallButton = document.getElementById("callee");
var localVideo = document.getElementById('localVideo');
var remoteVideo = document.getElementById('remoteVideo');
videoCallButton.addEventListener("click", initiateCall);
endCallButton.addEventListener("click", function (evt) {
wsc.send(JSON.stringify({"closeConnection": true }));
});
var sdpConstraints = {
'mandatory': {
'OfferToReceiveAudio': true,
'OfferToReceiveVideo': true
}
};
function prepareCall() {
peerConn = new RTCPeerConnection(peerConnCfg);
// send any ice candidates to the other peer
peerConn.onicecandidate = onIceCandidateHandler;
// once remote stream arrives, show it in the remote video element
peerConn.onaddstream = onAddStreamHandler;
};
// run start(true) to initiate a call
function initiateCall() {
prepareCall();
// get the local stream, show it in the local video element and send it
navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {
localVideoStream = stream;
localVideo.src = URL.createObjectURL(localVideoStream);
peerConn.addStream(localVideoStream);
createAndSendOffer();
}, function(error) { console.log(error);});
};
function answerCall() {
prepareCall();
// get the local stream, show it in the local video element and send it
navigator.getUserMedia({ "audio": true, "video": true }, function (stream) {
localVideoStream = stream;
localVideo.src = URL.createObjectURL(localVideoStream);
peerConn.addStream(localVideoStream);
createAndSendAnswer();
}, function(error) { console.log(error);});
};
wsc.onmessage = function (evt) {
var signal = null;
if (!peerConn) answerCall();
signal = JSON.parse(evt.data);
if (signal.sdp) {
console.log("Received SDP from remote peer.");
console.log("signal"+ signal);
peerConn.setRemoteDescription(new RTCSessionDescription(signal.sdp));
}
else if (signal.candidate) {
console.log("signal"+ signal.candidate);
console.log("Received ICECandidate from remote peer.");
peerConn.addIceCandidate(new RTCIceCandidate(signal.candidate));
} else if ( signal.closeConnection){
console.log("Received 'close call' signal from remote peer.");
endCall();
}else{
console.log("signal"+ signal.candidate);
}
};
function createAndSendOffer() {
peerConn.createOffer(
function (offer) {
var off = new RTCSessionDescription(offer);
peerConn.setLocalDescription(new RTCSessionDescription(off),
function() {
wsc.send(JSON.stringify({"sdp": off }));
},
function(error) { console.log(error);}
);
},
function (error) { console.log(error);}
);
};
function createAndSendAnswer() {
peerConn.createAnswer(
function (answer) {
var ans = new RTCSessionDescription(answer);
peerConn.setLocalDescription(ans, function() {
wsc.send(JSON.stringify({"sdp": ans }));
},
function (error) { console.log(error);}
);
},
function (error) {console.log(error);}
);
};
function onIceCandidateHandler(evt) {
if (!evt || !evt.candidate) return;
wsc.send(JSON.stringify({"candidate": evt.candidate }));
};
function onAddStreamHandler(evt) {
videoCallButton.setAttribute("disabled", true);
endCallButton.removeAttribute("disabled");
// set remote video stream as source for remote video HTML5 element
remoteVideo.src = window.URL.createObjectURL(evt.stream);
remoteVideo.play();
console.log("remote src : "+ remoteVideo.src);
};
function endCall() {
peerConn.close();
peerConn = null;
videoCallButton.removeAttribute("disabled");
endCallButton.setAttribute("disabled", true);
if (localVideoStream) {
localVideoStream.getTracks().forEach(function (track) {
track.stop();
});
localVideo.src = "";
}
if (remoteVideo){
remoteVideo.src = "";
window.URL.revokeObjectURL(remoteVideo);
}
};
One of the reasons for WebRTC blank / empty video is having high packet loss. In that scenario, in server and client logs it will show as the connection is successful and video is playing normally, so you won't see any warning or error.
To check if there is a high packet loss, you can go to about:webrtc on firefox, or chrome://webrtc-internals on chrome. For firefox, you can navigate to "RTP Stats". You'll see it shows Received: ... packets and Lost: ... packets. You can calculate packet loss ratio using these counts. For chrome, there is a graph for packet loss ratio. You might have a very high packet loss such as 70% for example.
If you have this extreme high packet loss, one reason is having a smaller MTU https://en.wikipedia.org/wiki/Maximum_transmission_unit on the client network interface than the MTU used by the server. For example, your client network interface can have MTU=1500 bytes when not connected to VPN, and MTU=1250 bytes when connected to VPN. If the server is sending RTP packets (over UDP) with MTU=1400, it can be received by the client if the client is not using VPN, but the packets larger than 1250 bytes will get dropped by the client network interface.
If you want to check the client MTU locally, you can run ifconfig on mac or linux.
Mac example, without example vpn:
en0: flags=8863<UP,BROADCAST,SMART,RUNNING,SIMPLEX,MULTICAST> mtu 1500
...
inet SOME_IP netmask 0xffffff00 broadcast 192.168.1.255
media: autoselect
status: active
Mac example, with example vpn:
utun2: flags=80d1<UP,POINTOPOINT,RUNNING,NOARP,MULTICAST> mtu 1250
inet SOME_IP --> SOME_IP netmask 0xffffffff
nd6 options=201<PERFORMNUD,DAD>
How to configure MTU for server:
If you are using GStreamer for WebRTC server, the payload generator element, for example rtpvp8pay has a property to set desired MTU value.
By using gst-inspect-1.0 rtpvp8pay you can see that it uses 1400 as MTU by default which can be larger than your client network interface can handle (e.g. 1250 on above example).
You can make it work by setting lower MTU on your GStreamer pipeline so that your client network interface won't drop majority of the packages anymore (package loss ratio can reduce to 0.01% just by changing MTU on GStreamer pipeline on the server).
When this is the case, the incoming video can work for ~10 seconds when VPN is freshly reconnected, then the incoming video can freeze and subsequent page refreshes can lead to just blank video with 70%+ packet loss.
This is a very specific scenario but when it happens it is a complete silent/hidden error so hopefully this helps someone.
add oniceconnectionstatechange to your prepeareCall Function and see if there is any ICE failure because of NAT issues
function prepareCall() {
peerConn = new RTCPeerConnection(peerConnCfg);
// send any ice candidates to the other peer
peerConn.onicecandidate = onIceCandidateHandler;
// once remote stream arrives, show it in the remote video element
peerConn.onaddstream = onAddStreamHandler;
peerConn.oniceconnectionstatechange = function(){
console.log('ICE state: ',peerConn.iceConnectionState);
}
};
in func did recieve remote video track perform a timer then in timer selector add track to view
Related
I’m experimenting with the ion echo-test example, which works for me (Chrome 98).
Instead of getting the stream from getUserMedia() though, I’d like to be able to capture it from a file (e.g. an mp4 file created with ffmpeg).
After associating the file to the local-video element, I have replaced this part in main.js:
Ion.LocalStream.getUserMedia({
resolution: resolutionBox.options[resolutionBox.selectedIndex].value,
codec:codecBox.options[codecBox.selectedIndex].value,
simulcast: sc,
audio: true,
})
.then((media) => {
localStream = media;
localVideo.srcObject = media;
localVideo.autoplay = true;
localVideo.controls = true;
localVideo.muted = true;
// joinBtns.style.display = "none";
localRTC.publish(media);
localDataChannel = localRTC.createDataChannel("data");
})
.catch(console.error);
with:
if (localVideo.captureStream) {
stream = localVideo.captureStream();
console.log('Captured stream from localVideo with captureStream', stream);
localVideo.autoplay = true;
localVideo.controls = true;
if (stream) {
localStream = new Ion.LocalStream(stream, {
resolution: resolutionBox.options[resolutionBox.selectedIndex].value,
codec:codecBox.options[codecBox.selectedIndex].value,
simulcast: sc,
audio: true,
video: true,
});
localRTC.publish(localStream);
localVideo.play()
}
localDataChannel = localRTC.createDataChannel("data");
}
The file plays in localVideo, and I can trace the ICE connectivity checks, confirming the connection is successful, but localRTC is not transmitting any video packet (and so remoteRTC doesn't receive anything and ontrackEvent doesn't trigger).
I have compared the stream structure in both the unmodified example case and my case, and I cannot see anything different.
No errors were logged in console.
Is there anything else I should do to create a proper capture stream to pass to localRTC.publish()?
I am fairly new in webRTC finding problems with its documentation. I cannot figure out why joiner does not receive stream from initiator since the messages on console look to me quite normal. Also i receive warnings about deprecated methods but not sure what to correct.
html:
navigator.getUserMedia = navigator.getUserMedia ||
navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.mediaDevices.getUserMedia ||
navigator.msGetUserMedia;
var isInitiator = false
, isChannelReady = false
, isStarted = false;
//Send 'create' or 'join' message to singnalling server
console.log('Create or join room', room);
socket.emit('create or join', room);
//Handle 'created' message coming back from server:
//this peer is the initiator
socket.on('created', function (room){
console.log('Created room ' + room);
isInitiator = true;
var video = $('#sidebar').append("<video class='student' autoplay='true'></video>");
});
//Handle 'join' message coming back from server:
//another peer is joining the channel
socket.on('join', function (room){
console.log('Another peer made a request to join room ' + room);
console.log('This peer is the initiator of room ' + room + '!');
isChannelReady = true;
var video = $('#sidebar').append("<video class='student' autoplay='true'></video>");
});
//Handle 'joined' message coming back from server:
//this is the second peer joining the channel
socket.on('joined', function (room){
console.log('This peer has joined room ' + room);
isChannelReady = true;
var video = $('#sidebar').append("<video class='student' autoplay='true'></video>");
navigator.getUserMedia({ video: true, audio: true },
function (stream) {
$('#sidebar').children().last().attr('src', window.URL.createObjectURL(stream))
if(!isStarted && typeof stream!= 'undefined' && isChannelReady) {
createPeerConnectionInit(stream);
isStarted = true;
} else{
}
}, function (error) {
console.log('error'+error);
});
});
socket.on('message', function (message){
if (message === 'got user media') {
}
else if (message.type === 'offer') {
if(isChannelReady){
console.log('Im the initiator. Channel is ready!!!');
createPeerConnectionNotInit(message);
isStarted = true;
}
}
else if (message.type === 'answer' && isStarted) {
peer.addAnswerSDP(message);
console.log('addAnswerSDP:', message);
}
else if (message.type === 'candidate' && isStarted) {
console.log("im adding candidate!!!");
var candidate = new RTCIceCandidate({sdpMLineIndex:message.label,
candidate:message.candidate});
peer.addICE(candidate);// εδω ο initiator προσθέτει στο ice τον candidate
}
else if (message === 'bye' && isStarted) {
}
});
function createPeerConnectionInit(stream){
peer = RTCPeerConnection({
attachStream : stream,
onICE : function (candidate) {
if (candidate) {
sendMessage({
type: 'candidate',
label: candidate.sdpMLineIndex,
id: candidate.sdpMid,
candidate: candidate.candidate});
} else {
console.log('End of candidates.');
}
},
onRemoteStream : function (stream) {
console.log('onRemoteStream Init = yes');
document.getElementById('video').src = stream;
},
onOfferSDP : function(sdp) {
console.log('sdp ='+JSON.stringify(sdp));
sendMessage(sdp);
}
});
}
function createPeerConnectionNotInit(offer_sdp){
peer = RTCPeerConnection({
onICE : function (candidate) {
if (candidate) {
sendMessage({
type: 'candidate',
label: candidate.sdpMLineIndex,
id: candidate.sdpMid,
candidate: candidate.candidate});
} else {
console.log('End of candidates.');
}
},
onRemoteStream : function (stream) {
console.log('onRemoteStream Not Init = yes');
document.getElementById('video').src = URL.createObjectURL(stream);;
},
// see below two additions ↓
offerSDP : offer_sdp,
onAnswerSDP : function(sdp) {
sendMessage(sdp);
}
});
}
Console log from initiator view:
sdp ={"type":"offer","sdp":"v=0\r\no=mozilla...THIS_IS_SDPARTA-53.0.3 8347568228516099874 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\na=fingerprint:sha-256
Sending message: Object { type: "candidate", label: 0, id: "sdparta_0", candidate: "candidate:0 1 UDP 2122187007 2a02:5…" } boardWithD3.js.html:798:13
Many same messages following..
addAnswerSDP: Object { type: "answer", sdp: "v=0 o=mozilla...THIS_IS_SDPARTA-53.…" } boardWithD3.js.html:727:17
adding-ice candidate:0 1 UDP 2122187007 2a02:582:1096:a500:f03d:34da:c0a:75b0 50729 typ host RTCPeerConnection-v1.5.js:264:13
A couple similar messages following…..
Console log from joiner view:
offer_sdp:{"type":"offer","sdp":"v=0\r\no=mozilla...THIS_IS_SDPARTA-53.0.3 8347568228516099874 0 IN IP4 0.0.0.0\r\ns=-\r\nt=0 0\r\na=fingerprint:sha-256 ………
ice-servers [{"url": "stun:23.21.150.121" },
{"url": "stun:stun.services.mozilla.com" }]
sdp-constraints {
"OfferToReceiveAudio": true,
"OfferToReceiveVideo": true
} RTCPeerConnection-v1.5.js:123:5
offer-sdp v=0 o=mozilla...THIS_IS_SDPARTA-53.0.3 8347568228516099874 0 IN IP4 0.0.0.0
……
WebRTC interfaces with the “moz” prefix (mozRTCPeerConnection, mozRTCSessionDescription, mozRTCIceCandidate) have been deprecated. RTCPeerConnection-v1.5.js:79:15
RTCIceServer.url is deprecated! Use urls instead. RTCPeerConnection-v1.5.js:79
onaddstream is deprecated! Use peerConnection.ontrack instead. RTCPeerConnection-v1.5.js:101
onRemoteStream Not Init = yes boardWithD3.js.html:784:21
Sending message: Object { type: "answer", sdp: "v=0 o=mozilla...THIS_IS_SDPARTA-53.…" } boardWithD3.js.html:798:13……
adding-ice candidate:0 1 UDP 2122187007 2a02:582:1096:a500:f03d:34da:c0a:75b0 50006 typ host RTCPeerConnection-v1.5.js:264:13
**Uncaught TypeError: Cannot set property 'src' of null
at Object.onRemoteStream (boardWithD3.js.html?andora:785)
at RTCPeerConnection.peer.onaddstream (RTCPeerConnection-v1.5.js:110)
**
adding-ice candidate:3 1 UDP 2122252543 2a02:582:1096:a500:7de6:9361:ecf4:476a 50007 typ host RTCPeerConnection-v1.5.js:264:13
followed by many similar messages…..
Sending message: Object { type: "candidate", label: 0, id: "sdparta_0", candidate: "candidate:0 1 UDP 2122187007 2a02:5…" } boardWithD3.js.html:798:13
followed by many similar messages…..
Thanks in advance
As per below log
Uncaught TypeError: Cannot set property 'src' of null
at Object.onRemoteStream (boardWithD3.js.html?andora:785)
at RTCPeerConnection.peer.onaddstream (RTCPeerConnection-v1.5.js:110)
Issue is in below method with video element.
onRemoteStream : function (stream) {
console.log('onRemoteStream stream', stream);
//document.getElementById('video').src = stream; // Issue could be here, add a video element with id="video" in html body.
document.getElementById('video').srcObject = stream; //As per latest API use srcObject instead of src
}
As #jib mentioned, you using old API's.
See the samples and demo for latest API's
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?
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.
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);
});
});
I am using Kurento Utils for WebRTC connection with Kurento Media Server (ver 5.x)
Inside the kurento-utils-js library during init the simplify codes are shown below:
if (!this.pc) {
this.pc = new RTCPeerConnection(server, options);
}
var ended = false;
pc.onicecandidate = function(e) {
// candidate exists in e.candidate
if (e.candidate) {
ended = false;
return;
}
if (ended) {
return;
}
var offerSdp = pc.localDescription.sdp;
console.log('ICE negotiation completed');
self.onsdpoffer(offerSdp, self);
ended = true;
};
My question is it seems like it is waiting until onicecandidate passing "null" value that signifies the process has ended and thus able to continue with creating SDP offer, but I couldn't find this behaviour in WebRTC specs?
My next question is, how else we can know the process of finding ice candidates has ended?
One of my PC in my office couldn't reached the code console.log('ICE negotiation completed'); as null value is not passed.
You could check the iceGatheringState property (run in chrome):
var config = {'iceServers': [{ url: 'stun:stun.l.google.com:19302' }] };
var pc = new webkitRTCPeerConnection(config);
pc.onicecandidate = function(event) {
if (event && event.target && event.target.iceGatheringState === 'complete') {
alert('done gathering candidates - got iceGatheringState complete');
} else if (event && event.candidate == null) {
alert('done gathering candidates - got null candidate');
} else {
console.log(event.target.iceGatheringState, event);
}
};
pc.createOffer(function(offer) {
pc.setLocalDescription(offer);
}, function(err) {
console.log(err);
}, {'mandatory': {'OfferToReceiveAudio': true}});
window.pc = pc;
http://www.w3.org/TR/webrtc/
4.3.1
" If the intent of the ICE Agent is to notify the script that:
[...]
The gathering process is done.
Set connection's ice gathering state to completed and let newCandidate be null."
So, you can either check for the ice gathering state against "completed" (in real life, this is not very reliable), or wait for a null candidate (super reliable).
I have problems with the WebRTC:
I use this code from one example about Video calls.
if (new_connection) {
console.log('New Peer Connection');
var peer_connection = {};
peer_connection.connection_id = msg.from_connection_id;
peer_connection.pc = createPeerConnection(peer_connection.connection_id,
false);
peer_connections.push(peer_connection);
$('#remote').prepend(remoteVideoHtml.replace('remoteVideoId', 'peer' +
peer_connection.connection_id));
}
//Now process the SDP JSON Blob received
for (var i in peer_connections) {
if (peer_connections[i].connection_id == msg.from_connection_id) {
try {
peer_connections[i].pc.processSignalingMessage(msg.data);
}catch (e) {
console.log("Failed to create processSignalingMessage, exception: " + e.message);
}
I need help because I have one problem here.
peer_connections[i].pc.processSignalingMessage(msg.data);
The problem is:
Object #<RTCPeerConnection> has no method 'processSignalingMessage'
I don't know how those functions works and how they are invoqued:
pc.onconnecting = function (msg) {
console.log('onSessionConnecting');
}
pc.onopen = function (msg) {
console.log('onSessionOpened');
}
pc.onaddstream = function (event) {
console.log('onRemoteStreamAdded add the remote peers video stream.');
var url = webkitURL.createObjectURL(event.stream);
$('#peer' + connection_id).attr({
src: url
});
}
I will appreciate any help.
The initial version of WebRTC in Chrome was based on ROAP and it used to have a processSignallingMessage() method. The current version based on JSEP and it has methods like setRometeDescription() or setLocalDescription() to inject the local SDP and the SDP received from other users.
You can still find this implementation in old versions of Chrome or in Bowser.