【问题标题】:How to abstract WebRTC offers?如何抽象 WebRTC 报价?
【发布时间】:2016-11-19 07:32:25
【问题描述】:

我在 WebRTC 的报价生成过程的抽象中遇到了一个奇怪的问题。似乎传入的冰候选者永远不会到达空候选者。在使用几乎相同的代码之前,我已经成功生成了报价,但无论出于何种原因,我的抽象版本只达到了 12 个候选人,而我原来的常规版本是 20 个。这太奇怪了,看起来代码几乎相同,但抽象的代码即使在同一个浏览器上也不起作用。

原始工作代码:

    var localConn = new webkitRTCPeerConnection({'iceServers':[{...}]});
    var remoteConn = new webkitRTCPeerConnection({'iceServers':[{...}]});

    function initMedia(localView, callback){
        navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
        var constraints = {audio:true,video:true};
        navigator.getUserMedia(constraints, successStream, errorStream);
        //onSuccess and Error functions
        function successStream(stream){
            window.stream = stream;
            if(window.URL){
                $('#'+localView).attr('src',window.URL.createObjectURL(stream));
            } else {
                $('#'+localView).attr('src',stream);
            }
            localConn.addStream(stream);
            remoteConn.addStream(stream);
            console.log('local Stream: '+ stream.id);
            callback();     //-> goes on to create new offer
        }
        function errorStream(error){
            console.log('navigator.getUserMedia error: ', error);
        }
    }

    //function that generates offer and sends it out to a callback
    function newOffer(callback){
        console.log('creating new offer');

        localConn.createOffer(function (sessionDescription){
            localConn.setLocalDescription(sessionDescription);
        }, function(error){
            console.log('Error setting local description: '+error);
        });
        createOffer();
        //gather ICE with a callback to handle/send generated offer
        function createOffer(){
            localConn.onicecandidate = function(iceEvent){
                console.log('gathering local ice');        //ice events fired (20 total)
                //upon gathering all local ice
                if(iceEvent.candidate === null){
                    console.log('local ice gathered');    //success
                    var offer = {'type': localConn.localDescription.type,
                                 'sdp': localConn.localDescription.sdp};
                    offer = JSON.stringify(offer);
                    console.log('offer created');
                    callback(offer);
                }  
            }
        }
    }

具有抽象功能的新版本(不获取空冰候选)

//general rtc vars
var localConn = new webkitRTCPeerConnection({'iceServers':[{'url':'stun:stun.1.google.com:19302'}]});
var remoteConn = new webkitRTCPeerConnection({'iceServers':[{'url':'stun:stun.1.google.com:19302'}]});
//var mediaStream;
var channel;

//creates a stream from webcam
//@params function streamHandle(stream)
function initStream(streamHandle){
    navigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
    var constraints = {audio:true,video:true};
    navigator.getUserMedia(constraints, successStream, errorStream);
    //onSuccess and Error functions
    function successStream(stream){
        window.stream = stream;
        console.log('TreRTC: Local Stream-'+ stream.id);
        //mediaStream = stream;
        localConn.addStream(stream);    //not sure if these need to be added before
        remoteConn.addStream(stream);   //or if they can be added in the creatOffer(stream) function
        streamHandle(stream);    //gets inserted into createOffer function
    }
    function errorStream(error){
        console.log('navigator.getUserMedia error: ', error);
    }
}

//creates an offer to be sent
//@params Stream stream (from getusermedia)
//@return string offer
function createOffer(stream){
    console.log('TreRTC: Creating Offer');
    //localConn.addStream(stream);    //tried both ways from top and from internal
    //remoteConn.addStream(stream);

    localConn.createOffer(function (sessionDescription){
        localConn.setLocalDescription(sessionDescription);
    }, function(error){
        console.log('Error setting local description: '+error);
    });

    localConn.onicecandidate = function(iceEvt){
        console.log('TreRTC: ICE in');            //ice events firing (12 total)
        if(iceEvt.candidate === null){
            console.log('TreRTC: ICE gathered');    //never reaches to this point...
            var offer = {'type': localConn.localDescription.type,
                         'sdp': localConn.localDescription.sdp};
            offer = JSON.stringify(offer);
            console.log('TreRTC: Offer initialized');
            return offer;    //returns offer as a string
        }    //could also specify a callback
    }
}

【问题讨论】:

  • 请问你这个代码是基于什么例子?它使用了非常古老的结构,例如旧版回调 API,a broken createObjectURL pattern,并且仅适用于 Chrome 浏览器启动,因为 webkit 前缀(我正在尝试追踪旧示例以更新它们)。
  • stun:stun.1.google.com:19305 不是 stun 服务器。您可能想使用 stun:stun.l.google.com:19305 进行测试

标签: javascript sockets stream webrtc getusermedia


【解决方案1】:
streamHandle(stream);    //gets inserted into createOffer function

您的 createOffer 函数和 initStream 函数完成之间可能存在竞争,因为当您计算它们启动的所有内容时,两者实际上是异步的(很难确定,因为您没有显示该代码)。

如果你想抽象 WebRTC,你应该考虑摆脱旧的遗留 API,而是使用 RTCPeerConnection 的modern promise-methods。在处理像这样的比赛时,Promise 是优于回调的抽象。

还可以考虑使用onnegotiationneeded 回调来触发协商,以解决这个问题(但要注意bug in Chrome)。

这是一个本地连接示例(在 Chrome 中使用 https fiddle):

var pc1 = new RTCPeerConnection(), pc2 = new RTCPeerConnection();

navigator.mediaDevices.getUserMedia({video: true, audio: true})
  .then(stream => pc1.addStream(video1.srcObject = stream))
  .catch(e => console.log(e));

pc1.onicecandidate = e => pc2.addIceCandidate(e.candidate);
pc2.onicecandidate = e => pc1.addIceCandidate(e.candidate);

pc2.ontrack = e => video2.srcObject = e.streams[0];
pc1.oniceconnectionstatechange = e => console.log(pc1.iceConnectionState);
pc1.onnegotiationneeded = e =>
  pc1.createOffer().then(d => pc1.setLocalDescription(d))
  .then(() => pc2.setRemoteDescription(pc1.localDescription))
  .then(() => pc2.createAnswer()).then(d => pc2.setLocalDescription(d))
  .then(() => pc1.setRemoteDescription(pc2.localDescription))
  .catch(e => console.log(e));
<video id="video1" width="160" height="120" autoplay muted></video>
<video id="video2" width="160" height="120" autoplay></video>
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

【讨论】:

    猜你喜欢
    • 2020-03-17
    • 1970-01-01
    • 2021-06-30
    • 1970-01-01
    • 2013-12-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-28
    相关资源
    最近更新 更多