Video streaming WebRTC视频/音频呼叫在不同网络上失败90%,但在同一网络上成功90%

Video streaming WebRTC视频/音频呼叫在不同网络上失败90%,但在同一网络上成功90%,video-streaming,webrtc,stun,django-channels,turn,Video Streaming,Webrtc,Stun,Django Channels,Turn,我使用webRTC和Django频道创建了视频聊天应用程序。在同一网络中使用时,我的应用程序90%的时间正常工作,但在不同网络中使用时失败。在不同网络上使用时,我无法看到远程人员的视频 我用了chrome://webrtc-internals/要跟踪我的webRTC响应,我得到了iceconnectionstate:在使用不同网络调用时失败 下面的截图是我在同一网络中获得成功时拍摄的 成功后,在同一网络上也出现addIceCandidateFailed错误,但视频通话正常工作,该错误仅出现在ch

我使用webRTC和Django频道创建了视频聊天应用程序。在同一网络中使用时,我的应用程序90%的时间正常工作,但在不同网络中使用时失败。在不同网络上使用时,我无法看到远程人员的视频

我用了chrome://webrtc-internals/要跟踪我的webRTC响应,我得到了iceconnectionstate:在使用不同网络调用时失败

下面的截图是我在同一网络中获得成功时拍摄的

成功后,在同一网络上也出现addIceCandidateFailed错误,但视频通话正常工作,该错误仅出现在chrome中,而不出现在firefox中。下面是屏幕截图

下面是我免费的STUN/TUNE服务器配置。我从StackOverflow的一个链接中获得了此配置。

 var peerConnectionConfig = {
        iceServers: [{
                urls: ["turn:173.194.72.127:19305?transport=udp",
                    "turn:[2404:6800:4008:C01::7F]:19305?transport=udp",
                    "turn:173.194.72.127:443?transport=tcp",
                    "turn:[2404:6800:4008:C01::7F]:443?transport=tcp"
                ],
                username: "CKjCuLwFEgahxNRjuTAYzc/s6OMT",
                credential: "u1SQDR/SQsPQIxXNWQT7czc/G4c="
            },
            {
                urls: ["stun:stun.l.google.com:19302"]
            }
        ]
    };
下面是我的webRTC javascript代码

$(function() {
    var initiator,pc;
    var isSender = false;
    var peerConnectionConfig = {
        iceServers: [{
                urls: ["turn:173.194.XX.127:19305?transport=udp",
                    "turn:[2404:XXXX:XXXX:C01::7F]:19305?transport=udp",
                    "turn:173.194.XX.127:443?transport=tcp",
                    "turn:[2404:XXXX:XXXX:C01::7F]:443?transport=tcp"
                ],
                username: "XXXXXXXXXX",
                credential: "YYYYYYYYYYY"
            },
            {
                urls: ["stun:stun.l.google.com:19302"]
            }
        ]
    };
    $.ajax({
        type: "GET",
        url: '/isRoomExist/?roomName=121' ,
        beforeSend: function() {},
        success: function(data) {
            data = JSON.parse(data);
            initiatorCtrl(data[0].flgInitiator);
        }
    });
    var ws_scheme = window.location.protocol == "https:" ? "wss" : "ws";
    var chatsock = new ReconnectingWebSocket(ws_scheme + '://' + window.location.host + "/chat" + window.location.pathname);

    function initiatorCtrl(event) {
        if (event == "fullhouse") {
            alert("full house");
        }
        if (event == "initiator") {
            initiator = false;
            init();
        }
        if (event == "not initiator") {
            initiator = true;
            init();
        }
    }

    function init() {
        var constraints = {
            audio: true,
            video: true
        };
        getUserMedia(constraints, connect, fail);
    }

    function connect(stream) {
        pc = new RTCPeerConnection(peerConnectionConfig);

        if (stream) {
            pc.addStream(stream);
            $('#local').attachStream(stream);
        }

        pc.onaddstream = function(event) {
            $('#remote').attachStream(event.stream);
            logStreaming(true);
        };
        pc.onicecandidate = function(event) {
            if (event.candidate) {
                chatsock.send(JSON.stringify(event.candidate));
                isSender = true;
            }
        };
        if (initiator) {
            createOffer();
        } else {
            log('waiting for offer...');
        }
        logStreaming(false);

        chatsock.onmessage = function(event) {
            var signal1 = JSON.parse(event.data);
            var signal = JSON.parse(signal1);

            if (isSender) {
                isSender = false
            } else {
                if (signal.sdp) {
                    if (initiator) {
                        receiveAnswer(signal);
                    } else {
                        receiveOffer(signal);
                    }
                } else if (signal.candidate) {
                    pc.addIceCandidate(new RTCIceCandidate(signal));
                }
            }
        };
    }

    function createOffer() {
        pc.createOffer(function(offer) {
            pc.setLocalDescription(offer, function() {
                chatsock.send(JSON.stringify(offer));
                isSender = true;
            }, fail);
        }, fail);
    }

    function receiveOffer(offer) {
        pc.setRemoteDescription(new RTCSessionDescription(offer), function() {
            pc.createAnswer(function(answer) {
                pc.setLocalDescription(answer, function() {
                    chatsock.send(JSON.stringify(answer));
                    isSender = true;
                }, fail);
            }, fail);
        }, fail);
    }

    function receiveAnswer(answer) {
        pc.setRemoteDescription(new RTCSessionDescription(answer));
    }
    function log() {
        console.log(Array.prototype.join.call(arguments, ' '))
        console.log.apply(console, arguments);
    }
    function logStreaming(streaming) {
        $('#streaming').text(streaming ? '[streaming]' : '[..]');
    }
    function fail() {
        console.error.apply(console, arguments);
    }
    jQuery.fn.attachStream = function(stream) {
        this.each(function() {
            this.src = URL.createObjectURL(stream);
            this.play();
        });
    };


});
根据您的webrtc内部结构,在设置远程描述之前,您将添加远程候选项

将候选人放入队列,直到收到远程描述。
设置远程描述后,
您可以从队列或onicecandidate向远程用户发送本地候选对象
并将远程候选者添加到您的pc

更新:
消息的顺序通常与POST顺序不同 因为POST是异步的,服务器可以处理 候选者比提供/回答(需要处理路由/cdr/分叉)更快(只是中继和更小的大小)

对远程候选人进行排队:我们需要在添加候选人之前处理远程报价。
对本地候选者进行排队:如果呼叫/优惠分岔到多个目的地(用户登录移动和浏览器或群组呼叫),则发起者只接受第一个应答。因此,所有接收端点都需要对本地候选对象排队,直到他们的答案得到确认


按照Ajay的建议检查邮件顺序确实有帮助

有一件事需要添加:链接到图表,使订单检查更容易: 和

还有一篇优秀的文章解释了这些图表:

但当我遇到addIceCandidateFailed时,我能够在同一网络上正确地进行视频通话。我将根据您的建议修改代码以解决addIceCandidateFailed错误。但我不明白为什么它不能在不同的网络上工作。感谢您的解决方案。请阅读。候选人需要在跨网络的对等点之间建立连接。这完全取决于网络/NAT条件。我之前读过这篇文章,对于NAT,我使用的是STUN/TURN。[{URL:[“TURN:173.194.72.127:19305?transport=udp”,“TURN:[2404:6800:4008:C01::7F]:19305?transport=udp”,“TURN:173.194.72.127:443?transport=tcp”,“TURN:[2404:6800:4008:C01::7F]:443?transport=tcp”],用户名:“ckjculwfegahnrjutayzc/s6OMT”,凭证:“u1SQDR/SQsPQIxXNWQT7czc/G4c=“},{url:[“stun:stun.l.google.com:19302”]})。我从stackoverflow链接之一获得此信息。我是否需要设置自己的回合服务器以获得更好的性能没有一个将提供免费回合服务器,您需要设置自己的回合服务器。`{URL:[“stun:stun.l.google.com:19302”]}`您可以使用此google stun服务器,如果您正确设置候选项,它通常在正常网络中工作。@jib我测试了最新的canary,候选项仅在setLocalDescription之后收集。最近我在某个地方读到,他们将在setLD之前攻击眩晕/翻转服务器,以加快收集速度。我更新了排队的答案。