在两次按下按钮之前,React-WebRTC应用程序不会建立连接

时间:2019-11-03 20:30:27

标签: javascript reactjs google-cloud-firestore connection webrtc

因此,这是我第一次在WebRTC工作,我正在尝试将this教程纳入我的网站。此后,仅根据我希望它的工作方式进行了一些更改。我将“通话”按钮更改为“就绪”按钮,在该按钮中,两个连接的用户都必须按下“准备就绪”,然后才能建立通话。另外,我目前正在使用React和Firestore,所以我认为我将使用firestore作为我的信令服务器,并且我做了一些更改以尝试使其在React组件中起作用。

无论出于何种原因,除非第二个人按下“就绪”,否则视频通话不会为我建立。这是有问题的代码:

readMessage = (data) => {
        console.log("Reading message..")
        console.log("readMessage | yourId: " + this.yourId);
        var msg = JSON.parse(data.message);
        console.log("readMessage | msg: ");
        console.log(msg);
        console.log("readMessage | sender: " + data.sender)
        var sender = data.sender;
        console.log("Comparing senderId and yourId")
        console.log(sender + " | " + this.yourId)
        if (sender != this.yourId) {
            console.log("senderId is not equal to currentUserId")
            console.log(this.pc)
            if (msg.ice != undefined){
                console.log("Adding ice candidate...")
                console.log("msg.ice: ");
                console.log(msg.ice);
                this.pc.addIceCandidate(new RTCIceCandidate(msg.ice));
            }
            else if (msg.sdp.type == "offer"){
                console.log("Msg type is offer");
                console.log("Setting pc's remote description")
                this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                .then(() => { 
                    console.log("Creating answer on pc")
                    return this.pc.createAnswer()
                })
                .then(answer => {
                    console.log("Answer created. Setting pc's local description to answer.")
                    console.log("Answer: ")
                    console.log(answer)
                    this.pc.setLocalDescription(answer);
                })
                .then(() => {
                    console.log("Sending answer message to server.")
                    this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription}))
                })
                .catch(err => console.log(err))

            }
            else if (msg.sdp.type == "answer"){
                console.log("Msg type is answer");
                console.log("Setting pc's remote description to the answer from the server.");
                this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))

            }
        } else {
            console.log("IDs are similar. Data was sent by this client.")
        }
}

showMyFace = () => {
        navigator.mediaDevices.getUserMedia({audio:true, video:true})
        .then((stream) => {
            console.log("Adding current user's webcam stream to yourVideo")
            console.log(stream)
            this.yourVideo.srcObject = stream;
            {/* for (const track of stream.getTracks()) {
                pc.addTrack(track);
            } */}
            this.pc.addStream(stream);
        }).catch(function(err) {
            console.log(err);
        });
}

establishCall = () => {
    this.pc.createOffer()
    .then(offer => this.pc.setLocalDescription(offer) )
        .then(() => this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription})) )
        .catch(err => {
            console.log(err)
        });
}

componentDidMount(){
        console.log("Component mounted.")
        this.showMyFace();

        this.pc.onicecandidate = (event => event.candidate?this.sendMessage(JSON.stringify({'ice':    event.candidate})): console.log("Sent All Ice"));

        this.pc.ontrack = (event => {
            console.log("onAddStream called. Adding stream object to friendsVideo.")
            console.log(event.streams[0])
            console.log(this.friendsVideo)
            this.friendsVideo.srcObject = event.streams[0]
            if (this.friendsVideo.srcObject != null){
                console.log("Stream connected.")
            }
            console.log("Logging state of friendsVideo.srcObject:")
            console.log(this.friendsVideo.srcObject)
        });
        this.countPlayersAndAssignNumber();
}

当两个用户都首次按下“就绪”时,最后一个人会创建一个要击中“就绪”的要约,然后发送他们的候选冰。被叫方收到要约并发送答案,它就是ICE候选人。但是,原始呼叫者没有收到答复,而且我似乎无法弄清楚原因。但是,只要报价创建者再次按下“就绪”按钮,就会再次发送报价和答案,这一次似乎没有发送ICE候选人,但是电话建立了。

从构造函数调用的Firestore监听器

 this.firestore.collection("games").doc(this.gameId).collection('connection').doc('data')
             .onSnapshot((doc) => {
                 if(doc.exists){
                    console.log(doc)
                    console.log("Current data: ", doc.data());
                    this.readMessage(doc.data())
                 }
             }, error => {
                console.log("Firestore listener on game connection data has failed. Error log: ")
                console.log(error)
             });

另外请注意,这是我在Stackoverflow上的第一篇文章。我仍在学习Javascript,React,尤其是WebRTC。欢迎提供有关编码甚至我如何格式化问题的任何建议。预先感谢您抽出宝贵时间在这里帮助我的人。

更新

我尝试通过在调用setRemoteDescription之前不调用getUserMedia来实现here中的逻辑。

readMessage函数:

readMessage = (data) => {
        console.log("Reading message..")
        console.log("readMessage | yourId: " + this.yourId);
        var msg = JSON.parse(data.message);
        console.log("readMessage | msg: ");
        console.log(msg);
        console.log("readMessage | sender: " + data.sender)
        var sender = data.sender;
        console.log("Comparing senderId and yourId")
        console.log(sender + " | " + this.yourId)
        if (sender != this.yourId) {
            console.log("senderId is not equal to currentUserId")
            console.log(this.pc)
            if (msg.ice != undefined){
                console.log("Adding ice candidate...")
                console.log("msg.ice: ");
                console.log(msg.ice);
                this.pc.addIceCandidate(new RTCIceCandidate(msg.ice));
            }
            else if (msg.sdp.type == "offer"){
                console.log("Msg type is offer");
                console.log("Setting pc's remote description")
                this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                .then(() => { 
                    console.log("Creating answer on pc")
                    return this.pc.createAnswer()
                })
                .then(answer => {
                    console.log("Answer created. Setting pc's local description to answer.")
                    console.log("Answer: ")
                    console.log(answer)
                    this.pc.setLocalDescription(answer);
                })
                .then(() => navigator.mediaDevices.getUserMedia({audio: true, video: true}))
                .then(stream => {
                    this.pc.addStream(stream)
                    this.yourVideo.srcObject = stream
                })
                .then(() => {
                    console.log("Sending answer message to server.")
                    this.sendMessage(JSON.stringify({'sdp': this.pc.localDescription}))
                })
                .catch(err => console.log(err))

            }
            else if (msg.sdp.type == "answer"){
                console.log("Msg type is answer");
                console.log("Setting pc's remote description to the answer from the server.");
                this.pc.setRemoteDescription(new RTCSessionDescription(msg.sdp))
                .then(() => navigator.mediaDevices.getUserMedia({audio: true, video: true}))
                .then(stream => {
                    this.pc.addStream(stream)
                    this.yourVideo.srcObject = stream
                })
            }
        } else {
            console.log("IDs are similar. Data was sent by this client.")
        }
    }

现在,其他客户端得到了答案,但是没有发送ICE候选人。

更新:解决方案

事实证明,问题出在我的Firestore。我尝试恢复到上面链接的教程中使用的旧的实时数据库代码,并且按预期建立了调用。但是,一旦我将实现交换到Firestore上,就开始出现问题。

我制作了另一种方法将冰候选者发送到与SDP数据不同的单独文档中,并从我的peerconnection.onicecandidate中调用此函数:

const sendIceCandidates = (data) => {
    console.log("SenderId: " + yourId);
    console.log("Message: " + data);
    // database.child("games").child(gameId).child("connection").set({ sender: senderId, message: data });
    firestore.collection('games').doc(gameId).collection('connection').doc('ice').set({ 
        sender: yourId,
        message: data
     }, err => {
         console.log("Error ocurred inserting data into firestore. Logging error: ")
         console.log(err)
     })
}

然后,我将Firestore侦听器更改为集合侦听器,并指定当对集合添加或修改某些内容时,它会执行相同的操作:

const sendIceCandidates = (data) => {
    console.log("SenderId: " + yourId);
    console.log("Message: " + data);
    // database.child("games").child(gameId).child("connection").set({ sender: senderId, message: data });
    firestore.collection('games').doc(gameId).collection('connection').doc('ice').set({ 
        sender: yourId,
        message: data
     }, err => {
         console.log("Error ocurred inserting data into firestore. Logging error: ")
         console.log(err)
     })
}

0 个答案:

没有答案