Приложение React-WebRTC не будет устанавливать соединение, пока кнопка не будет нажата дважды - PullRequest
0 голосов
/ 03 ноября 2019

Так что я впервые работаю в WebRTC, и я пытаюсь включить это учебное пособие на свой веб-сайт. С тех пор я сделал всего несколько изменений, основываясь только на том, как я хочу, чтобы это работало на меня. Я изменил кнопку «Позвонить» на кнопку «Готово», где оба подключенных пользователя должны будут нажать «Готово», после чего вызов будет установлен. Кроме того, в настоящее время я использую 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 вызывается изconstructor

 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. Любые советы по кодированию или даже как я отформатировал мой вопрос, все приветствуются. Заранее благодарю всех, кто нашел время, чтобы попытаться помочь мне.

Обновление

Я пытался реализовать логику из здесь , не вызывая getUserMediaдо вызова setRemoteDescription.

функция 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)
     })
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...