Ver Fonte

fix: 多人会议

shuisheng há 1 ano atrás
pai
commit
cd31eb9c8b

+ 69 - 36
src/hooks/use-websocket.ts

@@ -28,6 +28,7 @@ import {
   WSGetRoomAllUserType,
   WSLivePkKeyType,
   WsAnswerType,
+  WsBatchSendOffer,
   WsCandidateType,
   WsConnectStatusEnum,
   WsDisableSpeakingType,
@@ -45,7 +46,7 @@ import {
   WsStartRemoteDesk,
   WsUpdateJoinInfoType,
 } from '@/types/websocket';
-import { createNullVideo, createVideo, handleUserMedia } from '@/utils';
+import { createNullVideo, handleUserMedia } from '@/utils';
 import {
   WebSocketClass,
   prettierReceiveWsMsg,
@@ -505,26 +506,9 @@ export const useWebsocket = () => {
         } else if (data.live_room.type === LiveRoomTypeEnum.wertc_meeting_one) {
           if (data.receiver === mySocketId.value) {
             console.warn('是发给我的nativeWebRtcOffer-wertc_meeting_one');
-            await useTip({
-              content: '是否加入会议?',
-            });
-            const stream = await handleUserMedia({
-              video: true,
-              audio: true,
-            });
-            console.log('===66');
-            console.log(stream);
-            console.log(canvasVideoStream.value);
-            userStream.value = stream;
-            const video = createVideo({
-              appendChild: true,
-              show: true,
-            });
-            video.srcObject = stream;
-            console.log('kkkk11');
             updateWebRtcMeetingOneConfig({
               roomId: roomId.value,
-              userStream: userStream.value,
+              // userStream: userStream.value,
               anchorStream: canvasVideoStream.value,
             });
             if (networkStore.rtcMap.get(data.sender)) {
@@ -537,6 +521,10 @@ export const useWebsocket = () => {
               receiver: data.sender,
               videoEl: createNullVideo(),
             });
+            webRtcMeetingOne.addTrack({
+              stream: userStream.value,
+              receiver: data.sender,
+            });
             await webRtcMeetingOne.sendAnswer({
               sender: mySocketId.value,
               // data.data.receiver是接收者;我们现在new pc,发送者是自己,接收者肯定是房主,不能是data.data.receiver,因为data.data.receiver是自己
@@ -575,6 +563,8 @@ export const useWebsocket = () => {
         if (data.receiver === mySocketId.value) {
           console.warn('是发给我的nativeWebRtcCandidate');
           const rtc = networkStore.rtcMap.get(data.sender);
+          console.log('rtc', rtc);
+          console.log('sender', data.sender);
           rtc?.addIceCandidate(data.candidate);
         } else {
           console.error('不是发给我的nativeWebRtcCandidate');
@@ -693,12 +683,55 @@ export const useWebsocket = () => {
     );
 
     // 用户加入房间完成
-    ws.socketIo.on(WsMsgTypeEnum.joined, (data: WsJoinType['data']) => {
+    ws.socketIo.on(WsMsgTypeEnum.joined, async (data: WsJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.joined, data);
       appStore.setLiveRoomInfo(data.live_room);
       anchorInfo.value = data.anchor_info;
+      if (route.name === routerName.pull) {
+        // 当前是拉流页面
+        if (data.live_room?.type === LiveRoomTypeEnum.wertc_meeting_one) {
+          await useTip({
+            content: '是否加入会议?',
+          });
+          const stream = await handleUserMedia({
+            video: true,
+            audio: true,
+          });
+          userStream.value = stream;
+          networkStore.wsMap.get(roomId.value)?.send<WsBatchSendOffer['data']>({
+            requestId: getRandomString(8),
+            msgType: WsMsgTypeEnum.batchSendOffer,
+            data: {
+              roomId: roomId.value,
+            },
+          });
+        }
+      }
     });
 
+    // batchSendOffer
+    ws.socketIo.on(
+      WsMsgTypeEnum.batchSendOffer,
+      (data: WsBatchSendOffer['data']) => {
+        data.socket_list?.forEach((item) => {
+          if (item !== mySocketId.value) {
+            if (networkStore.rtcMap.get(item)) {
+              return;
+            }
+            webRtcMeetingOne.newWebRtc({
+              sender: mySocketId.value,
+              receiver: item,
+              videoEl: createNullVideo(),
+            });
+            webRtcMeetingOne.sendOffer({
+              sender: mySocketId.value,
+              receiver: item,
+            });
+          }
+        });
+      }
+    );
+
     // 其他用户加入房间
     ws.socketIo.on(WsMsgTypeEnum.otherJoin, (data: WsOtherJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.otherJoin, data);
@@ -763,22 +796,22 @@ export const useWebsocket = () => {
             roomId: roomId.value,
             anchorStream: canvasVideoStream.value,
           });
-          data.socket_list?.forEach((item) => {
-            if (item !== mySocketId.value) {
-              if (networkStore.rtcMap.get(item)) {
-                return;
-              }
-              webRtcMeetingOne.newWebRtc({
-                sender: mySocketId.value,
-                receiver: item,
-                videoEl: createNullVideo(),
-              });
-              webRtcMeetingOne.sendOffer({
-                sender: mySocketId.value,
-                receiver: item,
-              });
-            }
-          });
+          // data.socket_list?.forEach((item) => {
+          //   if (item !== mySocketId.value) {
+          //     if (networkStore.rtcMap.get(item)) {
+          //       return;
+          //     }
+          //     webRtcMeetingOne.newWebRtc({
+          //       sender: mySocketId.value,
+          //       receiver: item,
+          //       videoEl: createNullVideo(),
+          //     });
+          //     webRtcMeetingOne.sendOffer({
+          //       sender: mySocketId.value,
+          //       receiver: item,
+          //     });
+          //   }
+          // });
         } else if (data.live_room.type === LiveRoomTypeEnum.pk) {
           updateWebRtcMeetingPkConfig({
             roomId: roomId.value,

+ 14 - 0
src/hooks/webrtc/meetingOne.ts

@@ -144,6 +144,20 @@ export const useWebRtcMeetingOne = () => {
         }
       } catch (error) {
         console.error('meetingOne的sendAnswer错误');
+        console.log(error);
+      }
+    },
+    addTrack: ({ stream, receiver }: { stream; receiver: string }) => {
+      console.log('33333', receiver);
+      console.log(networkStore.rtcMap);
+      const rtc = networkStore.rtcMap.get(receiver);
+      console.log('33333', rtc);
+      console.log(stream);
+      if (rtc) {
+        stream.getTracks().forEach((track) => {
+          console.log('meetingOne的sendOffer插入track66', track.kind, track);
+          rtc.peerConnection?.addTrack(track, stream);
+        });
       }
     },
   };

+ 6 - 0
src/types/websocket.ts

@@ -79,6 +79,7 @@ export enum WsMsgTypeEnum {
   nativeWebRtcCandidate = 'nativeWebRtcCandidate',
 
   msrBlob = 'msrBlob',
+  batchSendOffer = 'batchSendOffer',
 }
 
 export interface IWsFormat<T> {
@@ -266,6 +267,11 @@ export type WsStartRemoteDesk = IWsFormat<{
   roomId: string;
 }>;
 
+export type WsBatchSendOffer = IWsFormat<{
+  roomId: string;
+  socket_list?: string[];
+}>;
+
 export type WsOfferType = IWsFormat<{
   live_room: ILiveRoom;
   sdp: any;

+ 7 - 7
src/utils/network/webRTC.ts

@@ -1,7 +1,6 @@
 import { getRandomString } from 'billd-utils';
 
 import { LiveLineEnum, MediaTypeEnum } from '@/interface';
-import { prodDomain } from '@/spec-config';
 import { AppRootState, useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { WsCandidateType, WsMsgTypeEnum } from '@/types/websocket';
@@ -574,17 +573,17 @@ export class WebRTCClass {
             // {
             //   urls: 'stun:stun.l.google.com:19302',
             // },
-            {
-              urls: `turn:hk.${prodDomain}`,
-              username: 'hss',
-              credential: '123456',
-            },
+            // {
+            //   urls: `turn:hk.${prodDomain}`,
+            //   username: 'hss',
+            //   credential: '123456',
+            // },
           ];
       this.peerConnection = new RTCPeerConnection({
         iceServers,
       });
       if (!this.isSRS) {
-        this.handleDataChannel();
+        // this.handleDataChannel();
       }
       this.handleStreamEvent();
       this.handleConnectionEvent();
@@ -644,6 +643,7 @@ export class WebRTCClass {
   /** 更新store */
   update = () => {
     const networkStore = useNetworkStore();
+    console.log('updateRtcMap', this.receiver);
     networkStore.updateRtcMap(this.receiver, this);
   };
 }

+ 17 - 6
src/views/push/index.vue

@@ -573,20 +573,21 @@ watch(
     renderFrame();
   }
 );
-const lockMap = ref(new Set());
+
 watch(
   () => networkStore.rtcMap,
   (newVal) => {
     newVal.forEach((item) => {
-      // if (appStore.allTrack.find((v) => v.mediaName === item.receiver)) {
-      //   return;
-      // }
+      if (appStore.allTrack.find((v) => v.mediaName === item.receiver)) {
+        return;
+      }
       // if (lockMap.value.has(item.localStream?.id)) {
       //   return;
       // }
       // if (item.localStream?.id) {
       //   lockMap.value.add(item.localStream?.id);
       // }
+      console.log('kkkkkkkkkk1111', item);
       addMediaOk({
         id: getRandomEnglishString(6),
         openEye: true,
@@ -1163,8 +1164,13 @@ function autoCreateVideo(data: {
       let canvasDom: Raw<fabric.Image>;
       let ratio;
       function main() {
-        const width = stream?.getVideoTracks()[0].getSettings().width!;
-        const height = stream?.getVideoTracks()[0].getSettings().height!;
+        const width =
+          stream?.getVideoTracks()[0].getSettings().width! ||
+          videoEl.videoWidth;
+        const height =
+          stream?.getVideoTracks()[0].getSettings().height! ||
+          videoEl.videoHeight;
+        console.log(width, height, '353333', videoEl.videoWidth);
         ratio = handleScale({ width, height });
         videoEl.width = width;
         videoEl.height = height;
@@ -1866,7 +1872,11 @@ async function addMediaOk(val: AppRootState['allTrack'][0]) {
     cacheStore.setResourceList(res);
     console.log('获取pk成功');
   } else if (val.type === MediaTypeEnum.metting) {
+    console.log('mettingmetting111');
     const event = val.stream;
+    console.log('mettingmetting111', event);
+    console.log(val, '22');
+
     if (!event) return;
     const videoTrack = val;
     videoTrack.rect = { left: 0, top: 0 };
@@ -1876,6 +1886,7 @@ async function addMediaOk(val: AppRootState['allTrack'][0]) {
       rect: videoTrack.rect,
       scaleInfo: videoTrack.scaleInfo,
     });
+    document.body.appendChild(videoEl);
     setScaleInfo({ canvasDom, track: videoTrack, scale });
     videoTrack.videoEl = videoEl;
     videoTrack.canvasDom = canvasDom;