欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

vue項(xiàng)目基于WebRTC實(shí)現(xiàn)一對(duì)一音視頻通話

 更新時(shí)間:2024年05月31日 11:48:29   作者:草樣的年華  
這篇文章主要介紹了vue項(xiàng)目基于WebRTC實(shí)現(xiàn)一對(duì)一音視頻通話效果,實(shí)現(xiàn)代碼分為前端和后端兩部分代碼,需要的朋友可以參考下

效果

前端代碼

<template>
  <div class="flex items-center flex-col text-center p-12 h-screen">
    <div class="relative h-full mb-4 fBox">
      <video id="localVideo"></video>
      <video id="remoteVideo"></video>
      <div v-if="caller && calling">
        <p class="mb-4 text-white">等待對(duì)方接聽...</p>
        <img style="width: 60px;" @click="hangUp" src="@/assets/guaDuang.png" alt="">
      </div>
      <div v-if="called && calling">
        <p>收到視頻邀請(qǐng)...</p>
        <div class="flex">
          <img style="width: 60px" @click="hangUp" src="@/assets/guaDuang.png" alt="">
          <img style="width: 60px" @click="acceptCall" src="@/assets/jieTing.png" alt="">
        </div>
      </div>
    </div>
    <div>
      <button @click="callRemote" style="margin-right: 10px">發(fā)起視頻</button>
      <button @click="hangUp" style="margin-left: 10px">掛斷視頻</button>
    </div>
  </div>
</template>
<script>
import { io, Socket } from "socket.io-client";
let roomId = '001';
export default {
  name: 'HelloWorld',
  props: {
    msg: String
  },
  data(){
    return{
      wsSocket:null,//實(shí)例
      called:false,// 是否是接收方
      caller:false,// 是否是發(fā)起方
      calling:false,// 呼叫中
      communicating:false,// 視頻通話中
      localVideo:null,// video標(biāo)簽實(shí)例,播放本人的視頻
      remoteVideo:null,// video標(biāo)簽實(shí)例,播放對(duì)方的視頻
      peer:null,
      localStream:null,
    }
  },
  methods:{
    // 發(fā)起方發(fā)起視頻請(qǐng)求
    async callRemote(){
      let that = this;
      console.log('發(fā)起視頻');
      that.caller = true;
      that.calling = true;
      // await getLocalStream()
      // 向信令服務(wù)器發(fā)送發(fā)起請(qǐng)求的事件
      await that.getLocalStream();
      that.wsSocket.emit('callRemote', roomId)
    },
    // 接收方同意視頻請(qǐng)求
    acceptCall(){
      console.log('同意視頻邀請(qǐng)');
      this.wsSocket.emit('acceptCall', roomId)
    },
    // 掛斷視頻
    hangUp(){
      this.wsSocket.emit('hangUp', roomId)
    },
    reset(){
      this.called = false;
      this.caller = false;
      this.calling = false;
      this.communicating = false;
      this.peer = null;
      this.localVideo.srcObject = null;
      this.remoteVideo.srcObject = null;
      this.localStream = undefined;
      console.log('掛斷結(jié)束視頻-------')
    },
    // 獲取本地音視頻流
    async getLocalStream(){
      let that = this;
      let obj = { audio: true, video: true };
      const stream = await navigator.mediaDevices.getUserMedia(obj); // 獲取音視頻流
      that.localVideo.srcObject = stream;
      that.localVideo.play();
      that.localStream = stream;
      return stream;
    }
  },
  mounted() {
    let that = this;
    that.$nextTick(()=>{
      that.localVideo = document.getElementById('localVideo');
      that.remoteVideo = document.getElementById('remoteVideo');
    })
    let sock = io('localhost:3000'); // 對(duì)應(yīng)服務(wù)的端口
    // 連接成功
    sock.on('connectionSuccess', (sock) => {
      console.log('連接成功:');
    });
    sock.emit('joinRoom', roomId) // 前端發(fā)送加入房間事件
    sock.on('callRemote', (sock) => {
      // 如果是發(fā)送方自己收到這個(gè)事件就不用管
      if (!that.caller){ // 不是發(fā)送方(用戶A)
        that.called = true; // 接聽方
        that.calling = true; // 視頻通話中
      }
    });
    sock.on('acceptCall',async ()=>{
      if (that.caller){
        // 用戶A收到用戶B同意視頻的請(qǐng)求
        that.peer = new RTCPeerConnection();
        // 添加本地音視頻流
        that.peer.addStream && that.peer.addStream(that.localStream);
        // 通過監(jiān)聽onicecandidate事件獲取candidate信息
        that.peer.onicecandidate = (event) => {
          if (event.candidate) {
            console.log('用戶A獲取candidate信息', event.candidate);
            // 通過信令服務(wù)器發(fā)送candidate信息給用戶B
            sock.emit('sendCandidate', {roomId, candidate: event.candidate})
          }
        }
        // 接下來用戶A和用戶B就可以進(jìn)行P2P通信流
        // 監(jiān)聽onaddstream來獲取對(duì)方的音視頻流
        that.peer.onaddstream = (event) => {
          console.log('用戶A收到用戶B的stream',event.stream);
          that.calling = false;
          that.communicating = true;
          that.remoteVideo.srcObject = event.stream;
          that.remoteVideo.play();
        }
        // 生成offer
        let offer = await that.peer.createOffer({
          offerToReceiveAudio: 1,
          offerToReceiveVideo: 1
        })
        console.log('offer', offer);
        // 設(shè)置本地描述的offer
        await that.peer.setLocalDescription(offer);
        // 通過信令服務(wù)器將offer發(fā)送給用戶B
        sock.emit('sendOffer', { offer, roomId })
      }
    })
    // 收到offer
    sock.on('sendOffer',async (offer) => {
      if (that.called){ // 接收方 - 用戶B
        console.log('收到offer',offer);
        // 創(chuàng)建自己的RTCPeerConnection
        that.peer = new RTCPeerConnection();
        // 添加本地音視頻流
        const stream = await that.getLocalStream();
        that.peer.addStream && that.peer.addStream(stream);
        // 通過監(jiān)聽onicecandidate事件獲取candidate信息
        that.peer.onicecandidate = (event) => {
          if (event.candidate) {
            console.log('用戶B獲取candidate信息', event.candidate);
            // 通過信令服務(wù)器發(fā)送candidate信息給用戶A
            sock.emit('sendCandidate', {roomId, candidate: event.candidate})
          }
        }
        // 接下來用戶A和用戶B就可以進(jìn)行P2P通信流
        // 監(jiān)聽onaddstream來獲取對(duì)方的音視頻流
        that.peer.onaddstream = (event) => {
          console.log('用戶B收到用戶A的stream',event.stream);
          that.calling = false;
          that.communicating = true;
          that.remoteVideo.srcObject = event.stream;
          that.remoteVideo.play();
        }
        // 設(shè)置遠(yuǎn)端描述信息
        await that.peer.setRemoteDescription(offer);
        let answer = await that.peer.createAnswer();
        console.log('用戶B生成answer',answer);
        await that.peer.setLocalDescription(answer);
        // 發(fā)送answer給信令服務(wù)器
        sock.emit('sendAnswer', { answer, roomId })
      }
    })
    // 用戶A收到answer
    sock.on('sendAnswer',async (answer) => {
      if (that.caller){ // 接收方 - 用戶A   判斷是否是發(fā)送方
        // console.log('用戶A收到answer',answer);
        await that.peer.setRemoteDescription(answer);
      }
    })
    // 收到candidate信息
    sock.on('sendCandidate',async (candidate) => {
      console.log('收到candidate信息',candidate);
      // await that.peer.addIceCandidate(candidate) // 用戶A和用戶B分別收到candidate后,都添加到自己的peer對(duì)象上
      // await that.peer.addCandidate(candidate)
      await that.peer.addIceCandidate(candidate)
    })
    // 掛斷
    sock.on('hangUp',()=>{
      that.reset()
    })
    that.wsSocket = sock;
  }
}
</script>

服務(wù)端代碼

const socket = require('socket.io');
const http = require('http');
const server = http.createServer()
const io = socket(server, {
    cors: {
        origin: '*' // 配置跨域
    }
});
io.on('connection', sock => {
    console.log('連接成功...')
    // 向客戶端發(fā)送連接成功的消息
    sock.emit('connectionSuccess');
    sock.on('joinRoom',(roomId)=>{
        sock.join(roomId);
        console.log('joinRoom-房間ID:'+roomId);
    })
    // 廣播有人加入到房間
    sock.on('callRemote',(roomId)=>{
        io.to(roomId).emit('callRemote')
    })
    // 廣播同意接聽視頻
    sock.on('acceptCall',(roomId)=>{
        io.to(roomId).emit('acceptCall')
    })
    // 接收offer
    sock.on('sendOffer',({offer,roomId})=>{
        io.to(roomId).emit('sendOffer',offer)
    })
    // 接收answer
    sock.on('sendAnswer',({answer,roomId})=>{
        io.to(roomId).emit('sendAnswer',answer)
    })
    // 收到candidate
    sock.on('sendCandidate',({candidate,roomId})=>{
        io.to(roomId).emit('sendCandidate',candidate)
    })
    // 掛斷結(jié)束視頻
    sock.on('hangUp',(roomId)=>{
        io.to(roomId).emit('hangUp')
    })
})
server.listen(3000, () => {
    console.log('服務(wù)器啟動(dòng)成功');
});

完整代碼gitee地址: https://gitee.com/wade-nian/wdn-webrtc.git

參考文章:基于WebRTC實(shí)現(xiàn)音視頻通話_npm create vite@latest webrtc-client

要是在撥打電話過程中,無法打開攝像頭或者麥克風(fēng),瀏覽器也沒有彈出獲取攝像頭及麥克風(fēng)的權(quán)限運(yùn)行,這是需要進(jìn)行瀏覽器安全源的設(shè)置,步驟如下:

1、在 chrome 中 輸入 chrome://flags/#unsafely-treat-insecure-origin-as-secure

2、找到Insecure origins treated as secure

3、添加你服務(wù)器的地址 例如:http://192.168.1.10:8080

4、選擇Enabled屬性

5、點(diǎn)擊右下角的Relaunch即可

到此這篇關(guān)于vue項(xiàng)目基于WebRTC實(shí)現(xiàn)一對(duì)一音視頻通話的文章就介紹到這了,更多相關(guān)vue音視頻通話內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Vue.js的Mixins使用方式

    Vue.js的Mixins使用方式

    Vue.js的Mixins功能允許封裝可復(fù)用的組件選項(xiàng),實(shí)現(xiàn)代碼復(fù)用和模塊化,Mixins可以包含數(shù)據(jù)、方法、生命周期鉤子等組件選項(xiàng),使用時(shí),Mixins中的選項(xiàng)會(huì)被混入組件中,優(yōu)先級(jí)低于組件自身選項(xiàng),優(yōu)點(diǎn)包括代碼復(fù)用、高靈活性和簡(jiǎn)單易用
    2024-09-09
  • 搭建Vue3+Vite+Ts腳手架的示例代碼

    搭建Vue3+Vite+Ts腳手架的示例代碼

    本文介紹了Vue3+Vite+Ts搭建腳手架的實(shí)現(xiàn),步驟包括創(chuàng)建項(xiàng)目、選擇技術(shù)棧、安裝依賴及運(yùn)行項(xiàng)目,旨在為開發(fā)者提供一個(gè)簡(jiǎn)易快速的搭建流程,感興趣的可以了解一下
    2024-11-11
  • vue+springboot實(shí)現(xiàn)項(xiàng)目的CORS跨域請(qǐng)求

    vue+springboot實(shí)現(xiàn)項(xiàng)目的CORS跨域請(qǐng)求

    這篇文章主要介紹了vue+springboot實(shí)現(xiàn)項(xiàng)目的CORS跨域請(qǐng)求,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-09-09
  • vue3使用svg圖標(biāo)的多種方式總結(jié)

    vue3使用svg圖標(biāo)的多種方式總結(jié)

    svg圖片在項(xiàng)目中使用的非常廣泛,下面這篇文章主要給大家介紹了關(guān)于vue3使用svg圖標(biāo)的多種方式,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-03-03
  • el-table實(shí)現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換)

    el-table實(shí)現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換)

    這篇文章主要介紹了el-table實(shí)現(xiàn)轉(zhuǎn)置表格的示例代碼(行列互換),本文結(jié)合示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2024-02-02
  • Vue 2.5.2下axios + express 本地請(qǐng)求404的解決方法

    Vue 2.5.2下axios + express 本地請(qǐng)求404的解決方法

    下面小編就為大家分享一篇Vue 2.5.2下axios + express 本地請(qǐng)求404的解決方法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2018-02-02
  • vue+webpack實(shí)現(xiàn)異步加載三種用法示例詳解

    vue+webpack實(shí)現(xiàn)異步加載三種用法示例詳解

    這篇文章主要介紹了vue+webpack實(shí)現(xiàn)異步加載的三種用法,文中給大家提到了vue+webpack實(shí)現(xiàn)異步組件加載的代碼,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友參考下吧
    2018-04-04
  • 基于Vuejs框架實(shí)現(xiàn)翻頁組件

    基于Vuejs框架實(shí)現(xiàn)翻頁組件

    這篇文章主要為大家詳細(xì)介紹了基于VueJs框架的翻頁組件,小巧精致,性能優(yōu)異的MVVM框架實(shí)現(xiàn)翻頁組件,也適用于angular,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • 淺談vue3中ref、toRef、toRefs?和?reactive的區(qū)別

    淺談vue3中ref、toRef、toRefs?和?reactive的區(qū)別

    本文主要介紹了淺談vue3中ref、toRef、toRefs?和?reactive的區(qū)別,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2022-07-07
  • vue使用vuedraggable對(duì)列表進(jìn)行拖拽排序

    vue使用vuedraggable對(duì)列表進(jìn)行拖拽排序

    vuedraggable 是一個(gè)基于 Vue 的拖拽排序組件,它可以讓你輕松地在 Vue 應(yīng)用中實(shí)現(xiàn)拖拽排序功能,下面就跟隨小編一起來了解下它的具體應(yīng)用吧
    2024-12-12

最新評(píng)論