当前位置:   article > 正文

vue项目基于WebRTC实现一对一音视频通话_vue实战 1-1 webrtc点对点语音视频通话

vue实战 1-1 webrtc点对点语音视频通话

效果

前端代码

  1. <template>
  2. <div class="flex items-center flex-col text-center p-12 h-screen">
  3. <div class="relative h-full mb-4 fBox">
  4. <video id="localVideo"></video>
  5. <video id="remoteVideo"></video>
  6. <div v-if="caller && calling">
  7. <p class="mb-4 text-white">等待对方接听...</p>
  8. <img style="width: 60px;" @click="hangUp" src="@/assets/guaDuang.png" alt="">
  9. </div>
  10. <div v-if="called && calling">
  11. <p>收到视频邀请...</p>
  12. <div class="flex">
  13. <img style="width: 60px" @click="hangUp" src="@/assets/guaDuang.png" alt="">
  14. <img style="width: 60px" @click="acceptCall" src="@/assets/jieTing.png" alt="">
  15. </div>
  16. </div>
  17. </div>
  18. <div>
  19. <button @click="callRemote" style="margin-right: 10px">发起视频</button>
  20. <button @click="hangUp" style="margin-left: 10px">挂断视频</button>
  21. </div>
  22. </div>
  23. </template>
  1. <script>
  2. import { io, Socket } from "socket.io-client";
  3. let roomId = '001';
  4. export default {
  5. name: 'HelloWorld',
  6. props: {
  7. msg: String
  8. },
  9. data(){
  10. return{
  11. wsSocket:null,//实例
  12. called:false,// 是否是接收方
  13. caller:false,// 是否是发起方
  14. calling:false,// 呼叫中
  15. communicating:false,// 视频通话中
  16. localVideo:null,// video标签实例,播放本人的视频
  17. remoteVideo:null,// video标签实例,播放对方的视频
  18. peer:null,
  19. localStream:null,
  20. }
  21. },
  22. methods:{
  23. // 发起方发起视频请求
  24. async callRemote(){
  25. let that = this;
  26. console.log('发起视频');
  27. that.caller = true;
  28. that.calling = true;
  29. // await getLocalStream()
  30. // 向信令服务器发送发起请求的事件
  31. await that.getLocalStream();
  32. that.wsSocket.emit('callRemote', roomId)
  33. },
  34. // 接收方同意视频请求
  35. acceptCall(){
  36. console.log('同意视频邀请');
  37. this.wsSocket.emit('acceptCall', roomId)
  38. },
  39. // 挂断视频
  40. hangUp(){
  41. this.wsSocket.emit('hangUp', roomId)
  42. },
  43. reset(){
  44. this.called = false;
  45. this.caller = false;
  46. this.calling = false;
  47. this.communicating = false;
  48. this.peer = null;
  49. this.localVideo.srcObject = null;
  50. this.remoteVideo.srcObject = null;
  51. this.localStream = undefined;
  52. console.log('挂断结束视频-------')
  53. },
  54. // 获取本地音视频流
  55. async getLocalStream(){
  56. let that = this;
  57. let obj = { audio: true, video: true };
  58. const stream = await navigator.mediaDevices.getUserMedia(obj); // 获取音视频流
  59. that.localVideo.srcObject = stream;
  60. that.localVideo.play();
  61. that.localStream = stream;
  62. return stream;
  63. }
  64. },
  65. mounted() {
  66. let that = this;
  67. that.$nextTick(()=>{
  68. that.localVideo = document.getElementById('localVideo');
  69. that.remoteVideo = document.getElementById('remoteVideo');
  70. })
  71. let sock = io('localhost:3000'); // 对应服务的端口
  72. // 连接成功
  73. sock.on('connectionSuccess', (sock) => {
  74. console.log('连接成功:');
  75. });
  76. sock.emit('joinRoom', roomId) // 前端发送加入房间事件
  77. sock.on('callRemote', (sock) => {
  78. // 如果是发送方自己收到这个事件就不用管
  79. if (!that.caller){ // 不是发送方(用户A)
  80. that.called = true; // 接听方
  81. that.calling = true; // 视频通话中
  82. }
  83. });
  84. sock.on('acceptCall',async ()=>{
  85. if (that.caller){
  86. // 用户A收到用户B同意视频的请求
  87. that.peer = new RTCPeerConnection();
  88. // 添加本地音视频流
  89. that.peer.addStream && that.peer.addStream(that.localStream);
  90. // 通过监听onicecandidate事件获取candidate信息
  91. that.peer.onicecandidate = (event) => {
  92. if (event.candidate) {
  93. console.log('用户A获取candidate信息', event.candidate);
  94. // 通过信令服务器发送candidate信息给用户B
  95. sock.emit('sendCandidate', {roomId, candidate: event.candidate})
  96. }
  97. }
  98. // 接下来用户A和用户B就可以进行P2P通信流
  99. // 监听onaddstream来获取对方的音视频流
  100. that.peer.onaddstream = (event) => {
  101. console.log('用户A收到用户B的stream',event.stream);
  102. that.calling = false;
  103. that.communicating = true;
  104. that.remoteVideo.srcObject = event.stream;
  105. that.remoteVideo.play();
  106. }
  107. // 生成offer
  108. let offer = await that.peer.createOffer({
  109. offerToReceiveAudio: 1,
  110. offerToReceiveVideo: 1
  111. })
  112. console.log('offer', offer);
  113. // 设置本地描述的offer
  114. await that.peer.setLocalDescription(offer);
  115. // 通过信令服务器将offer发送给用户B
  116. sock.emit('sendOffer', { offer, roomId })
  117. }
  118. })
  119. // 收到offer
  120. sock.on('sendOffer',async (offer) => {
  121. if (that.called){ // 接收方 - 用户B
  122. console.log('收到offer',offer);
  123. // 创建自己的RTCPeerConnection
  124. that.peer = new RTCPeerConnection();
  125. // 添加本地音视频流
  126. const stream = await that.getLocalStream();
  127. that.peer.addStream && that.peer.addStream(stream);
  128. // 通过监听onicecandidate事件获取candidate信息
  129. that.peer.onicecandidate = (event) => {
  130. if (event.candidate) {
  131. console.log('用户B获取candidate信息', event.candidate);
  132. // 通过信令服务器发送candidate信息给用户A
  133. sock.emit('sendCandidate', {roomId, candidate: event.candidate})
  134. }
  135. }
  136. // 接下来用户A和用户B就可以进行P2P通信流
  137. // 监听onaddstream来获取对方的音视频流
  138. that.peer.onaddstream = (event) => {
  139. console.log('用户B收到用户A的stream',event.stream);
  140. that.calling = false;
  141. that.communicating = true;
  142. that.remoteVideo.srcObject = event.stream;
  143. that.remoteVideo.play();
  144. }
  145. // 设置远端描述信息
  146. await that.peer.setRemoteDescription(offer);
  147. let answer = await that.peer.createAnswer();
  148. console.log('用户B生成answer',answer);
  149. await that.peer.setLocalDescription(answer);
  150. // 发送answer给信令服务器
  151. sock.emit('sendAnswer', { answer, roomId })
  152. }
  153. })
  154. // 用户A收到answer
  155. sock.on('sendAnswer',async (answer) => {
  156. if (that.caller){ // 接收方 - 用户A 判断是否是发送方
  157. // console.log('用户A收到answer',answer);
  158. await that.peer.setRemoteDescription(answer);
  159. }
  160. })
  161. // 收到candidate信息
  162. sock.on('sendCandidate',async (candidate) => {
  163. console.log('收到candidate信息',candidate);
  164. // await that.peer.addIceCandidate(candidate) // 用户A和用户B分别收到candidate后,都添加到自己的peer对象上
  165. // await that.peer.addCandidate(candidate)
  166. await that.peer.addIceCandidate(candidate)
  167. })
  168. // 挂断
  169. sock.on('hangUp',()=>{
  170. that.reset()
  171. })
  172. that.wsSocket = sock;
  173. }
  174. }
  175. </script>

服务端代码

  1. const socket = require('socket.io');
  2. const http = require('http');
  3. const server = http.createServer()
  4. const io = socket(server, {
  5. cors: {
  6. origin: '*' // 配置跨域
  7. }
  8. });
  9. io.on('connection', sock => {
  10. console.log('连接成功...')
  11. // 向客户端发送连接成功的消息
  12. sock.emit('connectionSuccess');
  13. sock.on('joinRoom',(roomId)=>{
  14. sock.join(roomId);
  15. console.log('joinRoom-房间ID:'+roomId);
  16. })
  17. // 广播有人加入到房间
  18. sock.on('callRemote',(roomId)=>{
  19. io.to(roomId).emit('callRemote')
  20. })
  21. // 广播同意接听视频
  22. sock.on('acceptCall',(roomId)=>{
  23. io.to(roomId).emit('acceptCall')
  24. })
  25. // 接收offer
  26. sock.on('sendOffer',({offer,roomId})=>{
  27. io.to(roomId).emit('sendOffer',offer)
  28. })
  29. // 接收answer
  30. sock.on('sendAnswer',({answer,roomId})=>{
  31. io.to(roomId).emit('sendAnswer',answer)
  32. })
  33. // 收到candidate
  34. sock.on('sendCandidate',({candidate,roomId})=>{
  35. io.to(roomId).emit('sendCandidate',candidate)
  36. })
  37. // 挂断结束视频
  38. sock.on('hangUp',(roomId)=>{
  39. io.to(roomId).emit('hangUp')
  40. })
  41. })
  42. server.listen(3000, () => {
  43. console.log('服务器启动成功');
  44. });

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

参考文章:基于WebRTC实现音视频通话_npm create vite@latest webrtc-client -- --template-CSDN博客y

要是在拨打电话过程中,无法打开摄像头或者麦克风,浏览器也没有弹出获取摄像头及麦克风的权限运行,这是需要进行浏览器安全源的设置,步骤如下:

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

2、找到Insecure origins treated as secure

3、添加你服务器的地址 例如:http://192.168.1.10:8080

4、选择Enabled属性

5、点击右下角的Relaunch即可

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/从前慢现在也慢/article/detail/757004
推荐阅读
相关标签
  

闽ICP备14008679号