почему требуется два предложения для установления sh webrt c соединения в chrome? - PullRequest
0 голосов
/ 26 апреля 2020

Я пытаюсь создать приложение для видео- и аудиозвонков с использованием webrt c, но здесь я сталкиваюсь со странной проблемой, то есть соединение не устанавливается в первый раз, но оно устанавливается, когда я снова отправляю предложение. Я попытался напечатать connectionState однорангового узла, он остается «новым» при первом щелчке, но изменяется при подключении и подключается при повторной отправке предложения. Я новичок в webrt c, я просто не могу понять это.

следующий код

import socketContext from '../components/socketContext';
import fetch from 'isomorphic-unfetch';
import params from '../config/params';
import SearchBar from '../components/SearchBar';
import withAuth from '../components/withAuth';
import Cookie from 'js-cookie';

class VideoConf extends React.Component{

    constructor(props){
        super(props);
        this.state = {
            friends: [],
            cameraStream: undefined,
            screenStream: undefined
        }
        this.RTCPeerConnection = undefined;
        this.RTCSessionDescription = undefined;
        this.peerConnection = undefined;
        this.configuration = {"iceServers": [{"urls": ["stun:stun.l.google.com:19302"]}]};
    }

    static contextType = socketContext;

    startConnection = async ()=>{
        try{
            const mediaStream = await navigator.mediaDevices.getUserMedia({audio:true,video:true});

            const localVideo = document.getElementById('local-video');

            localVideo.srcObject = mediaStream;
            localVideo.onloadedmetadata = function(e){
                localVideo.play();
            }

            this.peerConnection.ontrack = function ({ streams: [stream] }) {
                const remoteVideo = document.getElementById("remote-video");
                if (remoteVideo) {
                    remoteVideo.srcObject = stream;

                    remoteVideo.onloadedmetadata = function(e){
                        remoteVideo.play();
                    }
                }
            };

            mediaStream.getTracks().forEach(track => this.peerConnection.addTrack(track, mediaStream));
            window.videoStream = mediaStream;
            window.pc = this.peerConnection;
            this.setState({
                cameraStream: mediaStream
            })

        }catch(err){
            alert(err.message);
        }
    }

    shareScreen =  async ()=>{
        const mediaStream = await navigator.mediaDevices.getDisplayMedia({
            video: {
                cursor: 'always',
                displaySurface: 'browser'
            }
        });
        const localVideo = document.getElementById('local-video');
        localVideo.srcObject = mediaStream;
        localVideo.onloadedmetadata = function(e){
            localVideo.play();
        }

        this.peerConnection.getSenders().map(sender =>{
            if(sender.track.kind == 'video'){
                sender.replaceTrack(mediaStream.getTracks()[0]);
            }
        });

        this.setState({
            screenStream: mediaStream
        });
    }

    componentDidMount = async ()=>{

        const response = await fetch(`${params.hostname}/api/get-friends`,{
            headers:{
                Authorization:`Bearer ${Cookie.get('token')}`
            }
        })
        if(response.ok){
            const json = await response.json();
            this.setState({
                friends: json.data
            });
        }

        this.RTCPeerConnection = window.RTCPeerConnection;
        this.RTCSessionDescription = window.RTCSessionDescription;
        this.peerConnection = new this.RTCPeerConnection(this.configuration);

        let socket = this.context.socket;

        socket.on("call-made", async data => {
            await this.peerConnection.setRemoteDescription(
                new this.RTCSessionDescription(data.offer)
            );
            const answer = await this.peerConnection.createAnswer();
            await this.peerConnection.setLocalDescription(new this.RTCSessionDescription(answer));

            socket.emit("make-answer", {
                answer,
                to: data.socket
            });
        });

        socket.on("answer-made", async data => {
            await this.peerConnection.setRemoteDescription(
                new this.RTCSessionDescription(data.answer)
            );
        });

        // this.peerConnection.addEventListener("negotiationneeded", ev => {
        //     alert('ping it on');
        //     this.callUser(0);
        // });

        this.startConnection();

    }

    callUser = async (i) => {
        let socket = this.context.socket;
        let frndId = this.state.friends[i];

        const offer = await this.peerConnection.createOffer();
        await this.peerConnection.setLocalDescription(new this.RTCSessionDescription(offer));
        socket.emit('call-user',{
            offer,
            to: frndId.id
        });
    }

    render(){
        let {friends} = this.state;
        return(
            <div>
                <div className="container">
                    <div className = "row no-gutters">

                        <div className = "col-12 col-md-3 text-center p-3 border" style = {{minHeight:'60vh'}}>
                            <SearchBar handleSearch = {this.handleSearch} />
                            <div>
                                {
                                    friends.map((frnd,i)=>{
                                        return (
                                            <div key = {i} onClick = {()=>this.callUser(i)} style = {{cursor:'pointer'}}>
                                                {frnd.name}
                                            </div>
                                        );                                        
                                    })
                                }
                            </div>
                        </div>

                        <div className = "col-12 col-md-9 text-center">
                            <div>
                                <button className = "btn btn-success" onClick = {this.shareScreen}>Share screen</button>
                            </div>
                            <div className="video-container">
                                <video autoPlay id="remote-video" style={{width:'25vw',height:'25vh'}} ></video>
                                <video autoPlay muted id="local-video" style={{width:'25vw',height:'25vh'}} ></video>
                            </div>
                        </div>

                    </div>
                </div>
            </div>
        )
    }
}

export default withAuth(VideoConf);

Я использую сокеты для отправки и ответа на предложение, и я уверен, что нет проблем в серверной части. Было бы здорово помочь, если бы кто-то мог понять это.

1 Ответ

3 голосов
/ 26 апреля 2020

У вас нет обработчика для icecandidate , поэтому ваши браузеры не знают удаленных адресов для связи.

Это работает во второй раз, потому что некоторые кандидаты были собраны этот процесс называется струйка льда

...