现在是我试验 WebRTC 的时候了。
我想我理解了操作原理,但是远程视频是黑色的,我的错误在哪里?
当我添加一些 console.log() 一切都很好,这让我抓狂!
我正在使用 socket.io 发送信号:
io.sockets.on('connection', function(socket) {
socket.on('rtcOffer', function(offer) {
socket.broadcast.emit('rtcOffer', offer);
});
socket.on('rtcOfferAnswer', function(offer) {
socket.broadcast.emit('rtcOfferAnswer', offer);
});
socket.on('rtcCandidate', function(candidate) {
socket.broadcast.emit('rtcCandidate', candidate);
});
});
HTML:
<video id="localVideo" width="400" autoplay="autoplay" style="border:#000 1px solid;"></video>
<video id="remoteVideo" width="400" autoplay="autoplay" style="border:#000 1px solid;"></video>
<button type="button" id="bCall">Call</button>
JS:
navigator.getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia || navigator.msGetUserMedia || navigator.getUserMedia;
window.RTCPeerConnection = window.webkitRTCPeerConnection || window.mozRTCPeerConnection || window.RTCPeerConnection;
window.createSignalingChannel = window.mozCreateSignalingChannel || window.webkitCreateSignalingChannel || window.createSignalingChannel;
window.RTCSessionDescription = window.webkitRTCSessionDescription || window.mozRTCSessionDescription || window.RTCSessionDescription;
window.RTCIceCandidate = window.webkitRTCIceCandidate || window.mozRTCIceCandidate || window.RTCIceCandidate;
var _peerConn = null;
var _mediaConstraints = {
mandatory : {
/*OfferToReceiveAudio : true,*/
OfferToReceiveVideo : true
}
};
var _rtcConfig = {
iceServers : [{url : 'stun:stun.ekiga.net'},
{url : 'stun:stun.ideasip.com'},
{url : 'stun:stun.rixtelecom.se'},
{url : 'stun:stun.schlund.de'},
{url : 'stun:stun.l.google.com:19302'},
{url : 'stun:stun1.l.google.com:19302'},
{url : 'stun:stun2.l.google.com:19302'},
{url : 'stun:stun3.l.google.com:19302'},
{url : 'stun:stun4.l.google.com:19302'},
{url : 'stun:stun.voiparound.com'},
{url : 'stun:stun.voipbuster.com'},
{url : 'stun:stun.voipstunt.com'},
{url : 'stun:stun.voxgratia.org'},
{url : 'stun:stun.xten.com'},
{
url : 'turn:numb.viagenie.ca',
credential : 'muazkh',
username : 'webrtc@live.com'
}]
};
function call(localStream) {
_peerConn = new RTCPeerConnection(_rtcConfig, {
optional : [{
DtlsSrtpKeyAgreement : true
}]
});
_peerConn.onicecandidate = function(e) {
if(e.candidate) {
_peerConn.onicecandidate = null;
socketEmit('rtcCandidate', e.candidate);
}
};
_peerConn.onaddstream = function(e) {
if(e) {
$('#remoteVideo')[0].src = URL.createObjectURL(e.stream);
}
};
_peerConn.addStream(localStream);
_peerConn.createOffer(function(offer) {
_peerConn.setLocalDescription(new RTCSessionDescription(offer));
socketEmit('rtcOffer', offer);
}, logError, _mediaConstraints);
}
function callEnd() {
$('video').each(function() {
this.pause();
});
_peerConn.close();
}
function callAccept(localStream, offer) {
_peerConn = new RTCPeerConnection(_rtcConfig, {
optional : [{
DtlsSrtpKeyAgreement: true
}]
});
_peerConn.addStream(localStream);
_peerConn.onaddstream = function(e) {
if(e) {
$('#remoteVideo')[0].src = window.URL.createObjectURL(e.stream);
}
};
_peerConn.onicecandidate = function(e) {
if(e.candidate) {
_peerConn.onicecandidate = null;
socketEmit('rtcCandidate', e.candidate);
}
};
_peerConn.setRemoteDescription(new RTCSessionDescription(offer), function() {
_peerConn.createAnswer(function(answer) {
_peerConn.setLocalDescription(new RTCSessionDescription(answer));
socketEmit('rtcOfferAnswer', answer);
}, logError, _mediaConstraints);
}, logError);
}
function rtcCandidateIncoming(candidate) {
if(_peerConn === null) {
setTimeout(function() {
rtcCandidateIncoming(candidate);
}, 500);
return;
}
_peerConn.addIceCandidate(new RTCIceCandidate({
sdpMLineIndex : candidate.sdpMLineIndex,
candidate : candidate.candidate
}));
}
function userMediaAsk(callback) {
navigator.getUserMedia({
video : true/*,
audio : true*/
}, function(localStream) {
$('#localVideo')[0].src = window.URL.createObjectURL(localStream);
callback(localStream);
}, logError);
}
function logError(e) {
if(typeof e == typeof {}) {
console.log('Error : '+JSON.stringify(e));
}
else {
console.log('Error : '+e);
}
callEnd();
}
$(document).ready(function() {
$('#bCall').click(function() {
userMediaAsk(function(stream) {
call(stream);
});
});
socketRegisterSignal('rtcOffer', function(offer) {
userMediaAsk(function(stream) {
callAccept(stream, offer);
});
});
socketRegisterSignal('rtcOfferAnswer', function(answer) {
_peerConn.setRemoteDescription(new RTCSessionDescription(answer));
});
socketRegisterSignal('rtcCandidate', function(candidate) {
rtcCandidateIncoming(candidate);
});
});
window.onbeforeunload = function() {
if(_peerConn) {
_peerConn.close();
}
};
非常感谢 !!