1

我已经构建了一个 vuejs 超级基础的一对一 webRTC 视频聊天。我将 PubNub 用于信令,将 Xirsys 用于 ICE。

但是我在“通话”中收到此错误。但是页面加载正常。

错误 InvalidStateError:无法设置远程报价 sdp:在错误状态下调用:kHaveLocalOffer

<template>
    <div>
        <video ref="localVideo" id="localVideo" autoplay playsinline></video>
        <br />
        <video ref="remoteVideo" id="remoteVideo" autoplay playsinline></video>
        <br />
        <button type="button" class="btn btn-light btn-lg btn-block" @click="callClick">Call</button>
    </div>
</template>

<script>
    export default {
        data() {
            return {
                localVideo: {type: Object},
                remoteVideo: {type: Object},
                iceServers: [],
                myPeerConnection: {type: Object},
                channelName: ['testtesttest'],
                mediaConstraintsLocal: { 
                    video: {
                        width: { min: 640, ideal: 640 },
                        height: { min: 480, ideal: 480 },
                        aspectRatio: { ideal: 1.7777777778 },
                        frameRate: { min: 10, ideal: 30},
                        facingMode: { ideal: 'user' }
                    },
                    audio: {
                        sampleSize: 16,
                        channelCount: 2,
                        volume: 0
                    }
                },
                mediaConstraintsRemote: {
                    video: {
                        width: { min: 640, ideal: 640 },
                        height: { min: 480, ideal: 480 },
                        aspectRatio: { ideal: 1.7777777778 },
                        frameRate: { min: 10, ideal: 30},
                        facingMode: { ideal: 'user' }
                    },
                    audio: {
                        sampleSize: 16,
                        channelCount: 2,
                        volume: 0
                    }
                },
            };
        },

        mounted() {
            var _this = this;

            // LOAD PUBNUB
            this.pubnub.load();

            // SUBSCRIBE TO PUBNUB CHANNEL
            this.$pubnub.subscribe({
                channels: this.channelName
            });

            // REGISTER VIDEO DISPLAYS
            _this.localVideo = _this.$refs.localVideo;
            _this.remoteVideo = _this.$refs.remoteVideo;

            // GET PEER CONNECTION AND XIRSYS ICE SERVERS
            this.createPeerConnection();

            // GET USER MEDIA SET CONSTRAINTS AND STREAM
            navigator.mediaDevices.getUserMedia(this.mediaConstraintsLocal)
            .then(stream => {
                window.stream = stream;
                this.localVideo.srcObject = stream;
                this.localVideo.play();
            })
            .catch(function(errors) {
                console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
            });

            // REGISTER PUBNUB LISTENER
            _this.$pubnub.addListener({
                // PUBNUB ON MESSAGE
                message: function(message) {
                    // PUBNUB LISTENING CHANNEL
                    this.channelName = message.channel;

                    // ICE OFFER
                    if (message.ice) {
                        _this.myPeerConnection.addIceCandidate(new RTCIceCandidate(message.ice))
                        .catch(function(errors) {
                            console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
                        });
                    }

                    // SDP OFFER
                    if (message.message.type == 'offer') {
                        console.log(message.message.type + ' ON ' + message.channel);
                        console.log('SDP OFFER ' + _this.myPeerConnection.signalingState);

                        _this.myPeerConnection.setRemoteDescription(new RTCSessionDescription(message.message))
                        .then(function() {
                            return navigator.mediaDevices.getUserMedia(_this.mediaConstraintsRemote);
                        })
                        // GET VIDEO ADD VIDEO OBJECT
                        .then(function(stream) {
                            _this.remoteVideo.srcObject = stream;
                            _this.remoteVideo.play();
                            return _this.myPeerConnection.addStream(stream);
                        })
                        // PUBLISH ANSWER
                        .then(function() {
                            _this.myPeerConnection.createAnswer()
                            .then(function(answer) {
                                return _this.myPeerConnection.setLocalDescription(answer);
                            })
                            .then(function() {
                                // PUBNUB PUBLISH LOCAL DESCRIPTION AS ANSWER
                                console.log('PUBNUB PUBLISH LOCAL DESCRIPTION AS ANSWER ' + _this.myPeerConnection.signalingState);
                                _this.$pubnub.publish({
                                    message: _this.myPeerConnection.localDescription,
                                    channel: _this.channelName
                                });
                            });
                        })
                        .catch(function(errors) {
                            console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
                        });
                    }

                    // // SDP ANSWER
                    if (message.message.type == 'answer') {
                        console.log(message.message.type + ' ON ' + message.channel);
                        console.log('SDP ANSWER ' + _this.myPeerConnection.signalingState);

                        _this.myPeerConnection.setRemoteDescription(new RTCSessionDescription(message.message))
                        .then(function() {
                            console.log('SET REMOTE DESCRIPTION ' + _this.myPeerConnection.signalingState);
                            return navigator.mediaDevices.getUserMedia(_this.mediaConstraintsRemote);
                        })
                        // ADD VIDEO OBJECT
                        .then(function(stream) {
                            _this.remoteVideo.srcObject = stream;
                            _this.remoteVideo.play();
                            return _this.myPeerConnection.addStream(stream);
                        })
                        .catch(function(errors) {
                            console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
                        });
                    }
                }
            });
        },

        methods: {
            callClick() {
                console.log('call');
                var _this = this;

                // GET PEER CONNECTION AND XIRSYS ICE SERVERS
                this.createPeerConnection();

                // myPeerConnection
                console.log('this.myPeerConnection ' + this.myPeerConnection);

                // CREATE OFFER
                console.log('CREATE OFFER ' + this.myPeerConnection.signalingState);

                // ADD MEDIA TRACKS
                stream.getTracks().forEach(track => this.myPeerConnection.addTrack(track, stream));

                this.myPeerConnection.createOffer()
                .then(function(offer) {
                    console.log('SET LOCAL DESCRIPTION ' + _this.myPeerConnection.signalingState);
                    return _this.myPeerConnection.setLocalDescription(offer);
                })
                // PUBLISH OFFER
                .then(function() {
                    // PUBNUB PUBLISH LOCAL DESCRIPTION AS OFFER
                    console.log('PUBNUB PUBLISH LOCAL DESCRIPTION AS OFFER ' + _this.myPeerConnection.signalingState);
                    _this.$pubnub.publish({
                        message: _this.myPeerConnection.localDescription,
                        channel: _this.channelName
                    });
                })
                .catch(function(errors) {
                    console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
                });
            },

            createPeerConnection() {
                // GET XIRSYS ICE SERVERS
                Vue.http.options.root = '/root';
                Vue.http.headers.common['Authorization'] = 'Basic ' + btoa('ive:648');
                this.$http.put('https://global.xirsys.net/_turn/Default/')
                .then(response => (this.iceServers = response.data.v))
                .then(function() {
                    console.log('ICE SERVERS ' + this.iceServers);
                    this.myPeerConnection = new RTCPeerConnection(this.iceServers);
                })
                .catch(function(errors) {
                    console.log('%c Errors ' + errors, 'background: #222; color: #bada55');
                });
            }
        }
    }
</script>

任何帮助将不胜感激。

4

0 回答 0