WebRTC peerConnection 在不同设备之间始终失败。

huangapple go评论67阅读模式
英文:

WebRTC peerConnection always failed between different devices

问题

我使用webRTC为我的论文构建了视频通话应用程序。我已经构建了该应用程序,如果我在同一设备上使用它(不同的选项卡浏览器/不同的浏览器),它可以完美运行。然后,当我尝试呼叫另一个在另一台设备上登录的用户时,对等连接总是失败。我的应用程序已经在线,具有公共地址。这也发生在我的本地环境中。我已经使用了在这里测试时正常工作的Turn服务器。

在这种情况下,我的错误在哪里?

以下是我创建和处理对等连接的流程:

// 呼叫函数
export const call = async (from, to) => {
    // ... 你的代码 ...
}

// 回答呼叫函数
export const incomingCall = async (message) => {
    // ... 你的代码 ...
}

每个发送到对等用户的候选项我都保存在我的信令服务器的CandidatesQueue中,以等待呼叫状态,如果呼叫被接受并且对等用户上的对等连接已创建,然后我开始发送所有的候选项。

如果这些信息还不足够,这是我工作的存储库:
客户端存储库服务器存储库

我很困惑错误在哪里,是Turn服务器吗?还是我的代码?

如果你想尝试我的应用程序,这是链接:我的应用程序

你可以注册一个帐户并用你注册的帐户登录。

谢谢!

更新

在一次又一次的测试之后,有时可以连接,但有时无法连接。我已经尝试了3台不同的设备,但行为都相同,有时管理员1可以连接到客户1,但当客户1尝试连接到管理员1时,它无法连接。与另一个用户也是一样,行为真的很随机,我认为问题出在我的笔记本1上,但当我尝试另一台笔记本时,问题以随机方式发生。有任何想法吗?

英文:

I was building Video Call App using webRTC for my thesis. I already build the app and it works perfectly if I use the same device (different tab browser/different browser). Then, when I try to call another user that logged in on another device, the peer connection always failed. My app was already online at a public address. It happens in my local too. I already used Turn server that work when I tested it on here
. In that case, where is my mistake?

Here, the flow how I create and handle the peer connection :

// Call Function
export const call = async (from, to) => {
    let configuration = {
        iceServers: [
            {
                urls: "stun:stun1.l.google.com:19302"
            },
            {
                urls: "turn:a.relay.metered.ca:80",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:80?transport=tcp",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:443",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:443?transport=tcp",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
        ],
    };

    const peer = new RTCPeerConnection(configuration);

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true })
    peer.addTrack(stream.getTracks()[0], stream)

    const offer = await peer.createOffer();

    let message = {
        id : 'call',
        from : from,
        to : to,
        sdpOffer : offer,
        state: 'req_calling'
    };
    sendMessage(message);
    
    await peer.setLocalDescription(offer);
    WebRtcPeer.addPeer(peer)
    
    peer.onicecandidate = function (event) {
        if (event.candidate) {
            const message = {
                id : 'onIceCandidate',
                candidate : event.candidate,
                to : to,
                from: from
            }
            sendMessage(message);
        }
    }

    // get to know when connected to peer
    peer.onconnectionstatechange = function (event) {
        console.log('masuk sono')
        if (peer.connectionState === 'connected') {
            const message = {
                id: 'peerConnected',
                from: localStorage.getItem('me'),
                to: localStorage.getItem('they')
            }
            sendMessage(message)
        }
    }
}
// Answering Call Function

export const incomingCall = async (message) => {
    const configuration = {
        iceServers: [
            {
                urls: "stun:stun1.l.google.com:19302"
            },
            {
                urls: "turn:a.relay.metered.ca:80",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:80?transport=tcp",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:443",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
            {
                urls: "turn:a.relay.metered.ca:443?transport=tcp",
                username: "xxxxxxxxxx",
                credential: "xxxxxxxxxx",
            },
        ],
    }

    // create peer using RTC
    const peer = new RTCPeerConnection(configuration);

    peer.setRemoteDescription(new RTCSessionDescription(message.sdpOffer))

    const stream = await navigator.mediaDevices.getUserMedia({ audio: true, video: true })
    peer.addTrack(stream.getTracks()[0], stream)

    const answer = await peer.createAnswer();

    await peer.setLocalDescription(answer);

    WebRtcPeer.addPeer(peer)

    peer.onicecandidate = function (event) {
        if (event.candidate) {
            const msg = {
                id : 'onIceCandidate',
                candidate : event.candidate,
                to : message.from,
                from: message.to
            }
            sendMessage(msg);
        }
    }

    // get to know when connected to peer
    peer.onconnectionstatechange = function (event) {
        if (peer.connectionState === 'connected') {
            const message = {
                id: 'peerConnected',
                from: localStorage.getItem('me'),
                to: localStorage.getItem('they')
            }
            sendMessage(message)
        }
    }

    let response = {
        id: 'incomingCallResponse',
        from: message.from,
        callResponse: 'accept',
        sdpOffer: answer,
        state: 'acc_calling'
    }
    sendMessage(response);
    localStorage.setItem('they', message.from)
}

Every candidate that sends to peer user, I save it to CandidatesQueue in my signalling server because of waiting calling state, if the call is accepted and peer connection on the peer user was created, then I start to sending all the candidates.

If that information is still not enough, here is the repo that I work on :
client repo, server repo

I was confused where's the mistake, is it the Turn server ? or is it my code?

if you want to try my app, here's the link : myApp

you can register an account and log in with your registered account.

Thanks!

UPDATE

After doing testing over and over again, it could be connected, but sometimes can't. I already try with 3 different devices, but the behavior was same, sometimes admin1 can be connected to client1, but when client1 tries to connect to admin1 it can't. Also with another user, the behavior was really random, I think the problem was on my laptop1, but when I try the other laptop, the problem occur with random behavior. Any idea?

答案1

得分: 1

你是否在建立连接时使用了“完美协商”逻辑?

你可以参考以下页面获取详细信息:

https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Perfect_negotiation

英文:

Have you used the "perfect negotiation" logic when establish a connection?

You may refer to the following page for detail:

https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API/Perfect_negotiation

huangapple
  • 本文由 发表于 2023年6月5日 00:36:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/76401412.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定