【问题标题】:WebRTC works in Chrome but not FirefoxWebRTC 适用于 Chrome 但不适用于 Firefox
【发布时间】:2014-11-17 03:19:30
【问题描述】:

我阅读了有关相关问题的其他几个问题,但没有人回答我的问题。我有一个奇怪的问题,我可以使用 WebRTC 从 chrome 到 firefox 进行音频聊天,但不能使用 firefox 到 chrome。

基本上,当用户希望进行音频聊天时,他/她单击按钮#audioChatBtn,该按钮使用getUserMedia() 来设置流。问题是,从 Firefox 中单击 #audioChatBtn 不会在 Chrome 上触发 onaddstream 回调,但从 Chrome 中单击按钮会在 Firefox 上触发 onaddstream。因此,我可以从 Chrome 到 Firefox 进行音频聊天,但不能反过来。我已经尝试了几个小时来解决这个问题,但我希望这里有人能给出答案。

相关来源:

var configuration = {
    'iceServers': [
        { 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' }
    ]
};
var pc = RTCPeerConnection(configuration);
var myStream = null;
var currentAudioIndex = 0; // Number of created channels
var myAudioEnabled = false;

// send any ice candidates to the other peer
pc.onicecandidate = function (evt) {
    if (evt.candidate)
        $(document).trigger("persistState", { mode: 'rtc', 'candidate': evt.candidate });
};

// let the 'negotiationneeded' event trigger offer generation
pc.onnegotiationneeded = function () {
    pc.createOffer(localDescCreated, logError);
}

// once remote stream arrives, play it in the audio element
pc.onaddstream = function (evt) {
    console.log('creating and binding audio');

    var idx = (currentAudioIndex++);
    var audioElement = $('#audio' + idx);

    if (audioElement.length == 0) {
        var audio = $('<audio id="audio' + idx + '" autoplay>');
        $('body').append(audio);
        audioElement = $('#audio' + idx);
    }

    var audioObject = audioElement[0];
    attachMediaStream(audioObject, evt.stream);
};

function localDescCreated(desc) {
    pc.setLocalDescription(desc, function () {
        $(document).trigger("persistState", { mode: 'rtc', 'sdp': pc.localDescription });
    }, logError);
}

function logError(e) {
    bootbox.alert("Audio chat could not be started.");
}

function hasGetUserMedia() {
    return !!(navigator.getUserMedia || navigator.webkitGetUserMedia ||
              navigator.mozGetUserMedia || navigator.msGetUserMedia);
}

server.onPersist = function(msg) {
    if (msg.mode == "rtc") {
        if (msg.sdp)
            pc.setRemoteDescription(new RTCSessionDescription(msg.sdp), function () {
                // if we received an offer, we need to answer
                if (pc.remoteDescription.type == 'offer')
                    pc.createAnswer(localDescCreated, logError);
            }, logError);
        else
            pc.addIceCandidate(new RTCIceCandidate(msg.candidate));
    }
}



// On click, start audio chat from this user.
$('#audioChatBtn').click(function() {
    if (!hasGetUserMedia()) {
        bootbox.alert('Audio conferencing is not supported by your browser. (Currently only supported by Chrome, Firefox, and Opera web browsers.)');
        return;
    }

    if (myAudioEnabled) {
        myStream.stop();
        displayAlert('Streaming closed', 'Audio chat is off');
        $('#audioChatBtn').removeClass('btn-success').addClass('btn-primary');

    } else {
        getUserMedia({ video: false, audio: true }, function (localMediaStream) {
            myStream = localMediaStream;
            pc.addStream(localMediaStream);
            displayAlert('Streaming...', 'Audio chat is enabled');
            $('#audioChatBtn').removeClass('btn-primary').addClass('btn-success');
        }, logError);
    }

    myAudioEnabled = !myAudioEnabled;
});

我尝试过的

  • 在阅读this question后尝试在配置中使用'optional': [{ 'DtlsSrtpKeyAgreement': 'true' }]
  • 尝试为每个请求创建一个新的 RTCPeerConnection()
  • 尝试使用本机浏览器功能而不是 adapter.js
  • 探索了 Web 音频 API 而不是 getUserMedia()

【问题讨论】:

  • 尊敬的投票者,您提供的最接近的原因表明问题“必须包括所需的行为、特定的问题或错误以及在问题本身中重现它所需的最短代码”。我的问题包括所有这些元素。
  • 题外话,我想实现 webRTC,但是如果两者都有自己的 ID 而不是加载 .showing 所有连接的用户到服务器,是否可以让 user1 联系 user2?
  • 也许peer.js 会更容易使用然后重新发明*?
  • @arao6 酷.. 我已经为此 +1 了,希望有人能提供帮助。
  • @DmitryMatveev Peerjs 使用 node.js,我们使用 ASP.NET 和 SignalR 作为我们的信令服务器

标签: javascript html webrtc


【解决方案1】:

Firefox 目前不支持 onnegotiationneeded,因为我们目前不支持对现有连接进行重新协商。所有 addStream/addTrack 和单个 createDataChannel(如果您想使用它们)都需要在 createOffer() 或 createAnswer 之前完成。如果您在 createOffer 之前创建,可以在连接后创建 DataChannel()。

连接后添加流将不起作用。

一个(烦人的)替代方法是创建一组新的 PeerConnections 来替换旧的(使用旧对中的 DataChannel 作为信号通道以降低延迟)

解决这个问题在我们的优先级列表中居高不下,但需要发布更多版本。

【讨论】:

【解决方案2】:

经过大量调试,我意识到这个错误与我的代码无关,而与 Firefox 的 WebRTC 实现有关。 Firefox 不会触发onnegotiationneeded 回调,因此我必须使用超时来巧妙地完成它(并且希望在函数触发之前将流信息中继到远程客户端)。显然,这是一个 firefox 错误,我会报告它,希望他们在下一个版本中修复该错误。

        getUserMedia({ video: false, audio: true }, function (localMediaStream) {
            myStream = localMediaStream;
            pc.addStream(localMediaStream);
            displayAlert('Streaming...', 'Audio chat is enabled');
            $('#audioChatBtn').removeClass('btn-primary').addClass('btn-success');

            // Need this for Firefox
            if (webrtcDetectedBrowser == 'firefox')
                setTimeout(pc.onnegotiationneeded, 5000);

        }, logError);

【讨论】: