WebRTC需要帮助

时间:2015-05-20 17:40:31

标签: node.js webrtc p2p peer

现在是我尝试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();
    }
};

非常感谢!!

1 个答案:

答案 0 :(得分:1)

我无法确切地说出代码中导致问题的原因,但我的经验是,这是因为错过了冰候选人的交换。

当您执行setLocalDecription并且PeerConnection将通过onicecandidate方法欺骗icecandidates时,会生成Ice候选者,有时远程对等方还没有准备好接收候选者。我看到了您设置的计时器,但我确认您正在正确发送/接收它们。您可以使用chrome:// webrtc-internals url检查chrome中的冰状态。