WebRTC:Firefox无法接收视频作为来电者

时间:2014-08-15 15:18:33

标签: javascript google-chrome firefox webrtc

我是WebRTC的新手,正在尝试创建一个允许1对1视频会议的简单测试页。

到目前为止,我所拥有的内容适用于以下内容:

  • Chrome - >铬
  • Firefox - >铬

在以下情况下工作:

  • Firefox - >火狐
  • Chrome - >火狐

基本上,Firefox在被叫方时无法接收远程视频流。永远不会调用onaddstream处理程序,但我不知道为什么。

我在Firefox和Chrome之间找到的唯一区别是Firefox不会让ICE候选人涓涓细流;它们包含在初始商品/答案创建中,导致永远不会使用非空候选者调用onicecandidate处理程序。另一方面,Chrome确实会将候选者作为单独的消息发送到信令服务器。我不确定这是否是潜在的问题。

我正在使用Firefox Nightly 34和Chrome 36进行测试。信令服务器托管在我的局域网中,两台浏览器都在同一台计算机上运行。

以下代码基于http://www.html5rocks.com/en/tutorials/webrtc/basics/

var localVideo;
var remoteVideo;
var peerConnection;
var peerConnectionConfig = {'iceServers': [{'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]};
var isCaller;

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;

function pageReady() {
    localVideo = document.getElementById('localVideo');
    remoteVideo = document.getElementById('remoteVideo');

    serverConnection = new WebSocket('ws://myserver:3434');
    serverConnection.onmessage = gotMessageFromServer;
}

function start(_isCaller) {
    isCaller = _isCaller

    peerConnection = new RTCPeerConnection(peerConnectionConfig);
    peerConnection.onicecandidate = gotIceCandidate;
    peerConnection.onaddstream = gotRemoteStream;

    var constraints = {
        video: true,
        audio: true, 
    };

    if(navigator.getUserMedia) {
        navigator.getUserMedia(constraints, getUserMediaSuccess, getUserMediaError);
    } else {
        alert('Your browser does not support getUserMedia API');
    }
}

function getUserMediaSuccess(stream) {
    localStream = stream;
    localVideo.src = window.URL.createObjectURL(stream);

    peerConnection.addStream(stream);

    if(isCaller) {
        peerConnection.createOffer(gotDescription, createOfferError);
    } else {
        peerConnection.createAnswer(gotDescription, createAnswerError);
    }
}

function gotMessageFromServer(message) {
    if(!peerConnection) start(false);

    var signal = JSON.parse(message.data);
    if(signal.sdp) {
        peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp));
    } else if(signal.ice) {
        peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
    }
}

function gotIceCandidate(event) {
    if(event.candidate != null) {
        serverConnection.send(JSON.stringify({'ice': event.candidate}));
    }
}

function gotDescription(description) {
    peerConnection.setLocalDescription(description);
    serverConnection.send(JSON.stringify({'sdp': description}));
}

function gotMessageFromServer(message) {
    if(!peerConnection) start(false);

    var signal = JSON.parse(message.data);
    if(signal.sdp) {
        peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp));
    } else if(signal.ice) {
        peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
    }
}

function gotRemoteStream(event) {
    console.log("got remote stream");
    remoteVideo.src = window.URL.createObjectURL(event.stream);
}

// Error functions....

function getUserMediaError(error) {
    console.log(error);
}

function createOfferError(error) {
    console.log(error);
}

function createAnswerError(error) {
    console.log(error);
}

如果它有用,这是我的信令服务器。它是一个非常基本的Node.js脚本,它使用ws WebSocket库简单地将收到的消息广播到所有连接的客户端,在这种情况下只是另一个客户端。

var WebSocketServer = require('ws').Server;

var wss = new WebSocketServer({port: 3434});

wss.broadcast = function(data) {
    for(var i in this.clients) {
        this.clients[i].send(data);
    }
};

wss.on('connection', function(ws) {
    ws.on('message', function(message) {
        console.log('received: %s', message);
        wss.broadcast(message);
    });
});

非常感谢任何帮助!

1 个答案:

答案 0 :(得分:1)

原来我在致电setRemoteDescription()createAnswer()之间遇到了竞争条件。 Firefox要求允许在每次重新加载页面时使用网络摄像头,而Chrome只会在第一页加载时提出要求。这意味着当我在Firefox中呼叫createAnswer()时,视频流尚未存在,因为用户尚未允许访问网络摄像头。解决方案是在页面准备就绪时将调用移至getUserMedia()。这样,当发生来电时,用户已经允许访问网络摄像头,并且可以立即共享视频流。它并不完美,但它允许我的小测试页面工作,这就是我现在要做的。

以下是更新的代码,如果它可以帮助将来的任何人:

var localVideo;
var remoteVideo;
var peerConnection;
var peerConnectionConfig = {'iceServers': [{'url': 'stun:stun.services.mozilla.com'}, {'url': 'stun:stun.l.google.com:19302'}]};

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;

function pageReady() {
    localVideo = document.getElementById('localVideo');
    remoteVideo = document.getElementById('remoteVideo');

    serverConnection = new WebSocket('ws://sagan:3434');
    serverConnection.onmessage = gotMessageFromServer;

    var constraints = {
        video: true,
        audio: true, 
    };

    if(navigator.getUserMedia) {
        navigator.getUserMedia(constraints, getUserMediaSuccess, getUserMediaError);
    } else {
        alert('Your browser does not support getUserMedia API');
    }
}

function getUserMediaSuccess(stream) {
    localStream = stream;
    localVideo.src = window.URL.createObjectURL(stream);
}

function start(isCaller) {
    peerConnection = new RTCPeerConnection(peerConnectionConfig);
    peerConnection.onicecandidate = gotIceCandidate;
    peerConnection.onaddstream = gotRemoteStream;
    peerConnection.addStream(localStream);

    if(isCaller) {
        peerConnection.createOffer(gotDescription, createOfferError);
    }
}

function gotMessageFromServer(message) {
    if(!peerConnection) start(false);

    var signal = JSON.parse(message.data);
    if(signal.sdp) {
        peerConnection.setRemoteDescription(new RTCSessionDescription(signal.sdp), function() {
            peerConnection.createAnswer(gotDescription, createAnswerError);
        });
    } else if(signal.ice) {
        peerConnection.addIceCandidate(new RTCIceCandidate(signal.ice));
    }
}

function gotIceCandidate(event) {
    if(event.candidate != null) {
        serverConnection.send(JSON.stringify({'ice': event.candidate}));
    }
}

function gotDescription(description) {
    console.log('got description');
    peerConnection.setLocalDescription(description, function () {
        serverConnection.send(JSON.stringify({'sdp': description}));
    }, function() {console.log('set description error')});
}

function gotRemoteStream(event) {
    console.log("got remote stream");
    remoteVideo.src = window.URL.createObjectURL(event.stream);
}

// Error functions....

function getUserMediaError(error) {
    console.log(error);
}

function createOfferError(error) {
    console.log(error);
}

function createAnswerError(error) {
    console.log(error);
}