簡體   English   中英

使用VueJS的WebRTC:為什么不播放遠程視頻?

[英]WebRTC using VueJS: Why the remote video is not playing?

我正在制作一個示例應用程序,其中將有兩個視頻元素和一個“呼叫”按鈕。 第一個視頻元素( #localVideo )將顯示本地媒體流的輸出。 當我按下通話按鈕時,遠程視頻元素將播放遠程媒體流。 我已經在原始JavaScript中制作了相同的應用程序,效果很好。

在VueJS中,我正在制作一個WebRTC組件來獲取用戶媒體並將流設置為本地視頻元素。 當用戶按下呼叫按鈕時,我將創建兩個RTCPeerConnection對象,發送報價,設置本地描述,發送答案以及全部。

這是組件的模板-

<template>
  <div class="webRTC">
    <video id = "localVideo" playsinline autoplay muted></video>
    <button id = "call" v-on:click='call'> Call </button>
    <video id = "remoteVideo" playsinline autoplay controls></video>
  </div>
</template>

<script src="./webRTC.js"></script>

這是該組件的腳本-

export default {
  name: 'webRTC',
  sockets: {
    connect: function () {
      console.log('Socket IO connected!')
    },

    TestConnection: function () {
      console.log('Test connection successful!')
    }
  },

  data: function () {
    return {
      localStream: null,
      remoteStream: null,
      pc1: null,
      pc2: null
    }
  },

  methods: {
    call: function () {
      this.pc1 = new RTCPeerConnection()
      this.pc1.addEventListener('icecandidate', e => this.addIceCandidate(this.pc1, e))

      this.pc2 = new RTCPeerConnection()
      this.pc2.addEventListener('icecandidate', e => this.addIceCandidate(this.pc2, e))
      this.pc2.addEventListener('track', this.gotRemoteStrem)

      this.localStream.getTracks().forEach(track => {
        console.log('Adding local stream')
        this.pc1.addTrack(track, this.localStream)
      })

      this.pc1.createOffer({ offerToReceiveAudio: 1, offerToReceiveVideo: 1 }).then(this.gotDescription)
    },

    gotRemoteStrem: function (event) {
      console.log('Got Remote stream')
      let remoteVideo = document.querySelector('#remoteVideo')
      this.remoteStream = event.streams[0]
      remoteVideo.srcObject = event.streams[0]
    },

    gotDescription: function (description) {
      console.log('Got description 1')
      this.pc1.setLocalDescription(description)
      this.pc2.setRemoteDescription(description)

      this.pc2.createAnswer().then(this.gotDescription2)
    },

    gotDescription2: function (description) {
      console.log('Got description 2')
      this.pc2.setLocalDescription(description)
      this.pc1.setRemoteDescription(description)
    },

    addIceCandidate: function (pc, event) {
      this.getOtherPC(pc).addIceCandidate(event.candidate).then(this.addIceCandicateSuccess).catch(this.addIceCandicateFailure)
    },

    addIceCandicateSuccess: function () {
      console.log('Ice candidate added successfully')
    },

    addIceCandicateFailure: function () {
      console.log('Ice candidate failure')
    },

    getOtherPC: function (pc) {
      if (pc === this.pc1) {
        return this.pc2
      }

      return this.pc1
    },

    gotDevices: function (stream) {
      let localVideo = document.querySelector('#localVideo')
      this.localStream = stream
      localVideo.srcObject = stream
    },

    handleMediaError: function (error) {
      console.error('Error:' + error.name)
    }
  },

  created: function () {
    console.log('webRTC is created!')
    let prom = navigator.mediaDevices.getUserMedia({ audio: true, video: true }).then(this.gotDevices).catch(this.handleMediaError)
  }
}

本地視頻顯示正常。 我面臨的問題是,當我按下“ Call按鈕時,遠程視頻沒有顯示任何內容,而是在屏幕截圖中看到了一個加載圓圈。 也沒有控制台錯誤。

在此處輸入圖片說明

我已經調試並看到了本地和遠程視頻的srcObject ,它們似乎是相同的- 在此處輸入圖片說明 誰能告訴我我做錯了什么嗎? 還有其他方法可以調試嗎?

注意:

可以從此處下載項目/源代碼,如果需要,可以下載並檢查代碼。 我將嘗試准備一個代碼筆-https://drive.google.com/open ? id = 1e7C0ojZ0jT7EXFNtCKcWpJBpKd_mWi_s

使用沒有async / await promise需要手動傳播錯誤並進行檢查。

添加一個catch例如在這里查看錯誤:

this.pc1.createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1})
  .then(this.gotDescription)
  .catch(e => console.log(e)); // <-- here

...並且您應該看到在gotDescription()thisundefined 那是因為您要將成員函數作為回調傳遞給then函數,而最終沒有使用this調用它。 使用this.gotDescription.bind(this)或(nicer)箭頭功能。 例如:

this.pc1.createOffer({offerToReceiveAudio: 1, offerToReceiveVideo: 1})
  .then(offer => this.gotDescription(offer)) // arrow function invoking on this
  .catch(e => console.log(e));

此外,除非您返回所有的Promise ,否則它們不會形成捕獲所有錯誤的單一鏈。

所有這些調用都會返回promise,您將忽略它們:

/* const unusedPromise1 = */ this.pc1.setLocalDescription(description)
/* const unusedPromise2 = */ this.pc2.setRemoteDescription(description)
/* const unusedPromise3 = */ this.pc2.createAnswer().then(this.gotDescription2)

幸運的是(可能令人困惑), RTCPeerConnection自動將在其上進行的操作排隊,因此,如果沒有錯誤(可能會被瀏覽器吞沒),這可以實際起作用。

相反,要捕獲錯誤,請執行以下操作:

this.pc1.setLocalDescription(description)
.then(() => this.pc2.setRemoteDescription(description))
.then(() => this.pc2.createAnswer())
.then(answer => this.gotDescription2(answer))
.catch(e => console.log(e))

或使用更好的async / await語法正確傳播錯誤:

gotDescription: async function (description) {
  console.log('Got description 1')
  await this.pc1.setLocalDescription(description)
  await this.pc2.setRemoteDescription(description)
  await this.gotDescription2(await this.pc2.createAnswer());
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM