WebRTC - 如何在提供和答案后建立对等连接

时间:2013-11-30 01:51:29

标签: node.js webrtc

我有一个运行用户将连接到的node.js。将生成要约和答案,并通过node.js发送。

我正在尝试建立对等连接并通过摄像头流发送。我尝试了我的代码而没有使用ICE候选者作为同一子网中的计算机。之后我尝试实施ICE。我不确定我是否已经做好了,或者如果计算机在同一个子网上甚至需要它。

var localStream;
//Connect to signaling server
var signalingChannel = io.connect('http://85.134.54.193:8001');
console.log("Connect to signaling server");
var servers = null;

var video1;
var video2;
var audio1;
var audio2;

var cfg = {"iceServers":[{"url":"stun:stun.l.google.com:19302"}]};//{ "iceServers": [{ "url": "stun:stun.l.google.com:19302" }] };
var con = { 'optional': [{'DtlsSrtpKeyAgreement': true}, {'RtpDataChannels': true }] };
var peerConnection;

//Runs after the page has been loaded
window.onload=function(){
    //Gets ID for the video element which will display the local stream
    video1 = document.getElementById("audio1");
    //Gets ID for the video element which will display the remote stream
    video2 = document.getElementById("audio2");
    audio1 = document.getElementById("audio1");
    audio2 = document.getElementById("audio2");
    }

//Start button function
function caller(){
    peerConnection = new webkitRTCPeerConnection(cfg);
    navigator.webkitGetUserMedia({'audio':true, video:true}, function (stream) {
        console.log("Got local audio", stream);
        video1.src = window.webkitURL.createObjectURL(stream)
        peerConnection.addStream(stream);
    }, 
    function ( err ) {
        console.log( 'error: ', err );
    });

    console.log("Calling");
    //Create Offer
    peerConnection.createOffer(function (offerDesc) {
        console.log("Created local offer", offerDesc.sdp);
        peerConnection.setLocalDescription(offerDesc);
    }, function () { console.warn("Couldn't create offer"); });

    //ICE Candidates Generator
    peerConnection.onicecandidate = function(evt) {
        //When The Ice Gathering is complete
        if (evt.target.iceGatheringState == "complete") {
            //Create a new offer with ICE candidates
            peerConnection.createOffer(function(offer) {
                console.log("Offer with ICE candidates: " + offer.sdp);
                signalingChannel.emit('offer', JSON.stringify(offer));
                console.log("offer sent");
                signalingChannel.on('answer', function(data){
                    console.log("Receive answer");
                    //The answer is set as the remote description for the offerer
                    peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(data)));
                    console.log("Set remote desc");
                    peerConnection.onaddstream = gotRemoteStream;
                    console.log("Add remote stream to peer connection");
                });
            });
        }
    }

}

function answerer(){
    peerConnection = new webkitRTCPeerConnection(cfg);
    navigator.webkitGetUserMedia({'audio':true, video:true}, function (stream) {
        console.log("Got local audio", stream);
        video1.src = window.webkitURL.createObjectURL(stream)
        peerConnection.addStream(stream);
    }, 
    function ( err ) {
        console.log( 'error: ', err );
    });
    console.log("Answering");
    //Listen for offer
    signalingChannel.on('offer', function(data){
        console.log("Offer Received");
        //Set the remote description from caller's local description
        peerConnection.setRemoteDescription(new RTCSessionDescription(JSON.parse(data)));
        //Generate answer after getting the remote description
        peerConnection.createAnswer(function(sessionDescription) {
                //Set local description
                peerConnection.setLocalDescription(sessionDescription);
                //The local desc will be the answer sent back to offerer
                signalingChannel.emit('answer', JSON.stringify(sessionDescription));
                console.log("Answer sent");
                });
    });

}

function gotRemoteStream(event){
    video2.src = window.webkitURL.createObjectURL(event.stream);
}

2 个答案:

答案 0 :(得分:1)

以下是我今天(2014年2月)在Chrome中发布的一系列事件。这是针对简化的情况,其中对等体1将视频流式传输到对等体2。

  1. 为对等方设置一些交换消息的方法。 (人们如何实现这一点的不同之处在于,不同的WebRTC代码示例如此难以理解,令人遗憾。但在精神上,在您的代码组织中,尝试将此逻辑与其他代码分开。)
  2. 在每一侧,为重要的信令消息设置消息处理程序。你可以设置它们并将它们保留下来。有三个核心消息要处理&发送:
    • 从另一方发送的冰候选人==>用它来呼叫addIceCandidate
    • 优惠讯息==> SetRemoteDescription用它,然后回答&发送它
    • 回答消息===> SetRemoteDescription随身携带
  3. 在每一侧,创建一个新的peerconnection对象,并为其执行重要事件的事件处理程序:onicecandidate,onremovestream,onaddstream等。
    • 冰候选人===>将其发送到另一方
    • stream added ===>将它附加到视频元素,以便您可以看到它
  4. 当两个对等方都存在并且所有处理程序都已到位时,对等方1会获得某种触发消息以启动视频捕获(使用getUserMedia调用)
  5. 一旦getUserMedia成功,我们就有了一个流。在对等方1的对等连接对象上调用addStream
  6. 然后 - 只有那时 - 同伴1提出要约
  7. 由于我们在步骤2中设置了处理程序,因此对等方2获取此处并发送答案
  8. 与此同时(并且有点模糊),对等连接对象开始产生冰候选者。它们在两个同伴之间来回传递并处理(上面的步骤2和3)
  9. 由于两个条件,流式传输本身是不透明的:
    • 提供/回答交流
    • 冰候选人收到,交换和添加
  10. 当我想要更改流时,我将返回步骤3并设置一个新的对等连接对象并再次执行整个提议/回答。

答案 1 :(得分:0)

为什么在创建答案之前等待ICE完成?怎么样同时做它们?这可能有所帮助,因为它只是意味着同时工作。如果你可以在此之后发布你的日志,当它仍然无法工作时,我们可以尝试进一步调试它。如果您想查看此音频示例(它同时发送音乐音频和麦克风音频),请选中heregithub source。使用node.js和ws插件制作的服务器。音频连接适用于webRTC。