Bladeren bron

feat: 优化多对多

shuisheng 3 jaren geleden
bovenliggende
commit
2b46fda4e1

+ 70 - 59
src/hooks/use-pull.ts

@@ -183,7 +183,7 @@ export function usePull({
       instance.send({
         msgType: WsMsgTypeEnum.heartbeat,
       });
-    }, 1000 * 30);
+    }, 1000 * 5);
   }
 
   function closeWs() {
@@ -210,18 +210,17 @@ export function usePull({
     });
   }
 
-  function addTransceiver() {
+  function addTransceiver(socketId: string) {
+    console.log('333addTransceiver', localStream.value);
     if (!localStream.value) return;
-    liveUserList.value.forEach((item) => {
-      if (item.socketId !== getSocketId()) {
-        localStream.value.getTracks().forEach((track) => {
-          const rtc = networkStore.getRtcMap(
-            `${roomId.value}___${item.socketId}`
-          );
-          rtc?.addTransceiver(track, localStream.value);
-        });
-      }
-    });
+    if (socketId !== getSocketId()) {
+      console.log(3333);
+      localStream.value.getTracks().forEach((track) => {
+        const rtc = networkStore.getRtcMap(`${roomId.value}___${socketId}`);
+        console.log(999999);
+        rtc?.addTransceiver(track, localStream.value);
+      });
+    }
   }
 
   function addTrack() {
@@ -259,49 +258,50 @@ export function usePull({
     });
   }
 
-  function batchSendOffer() {
-    liveUserList.value.forEach(async (item) => {
-      if (
-        !offerSended.value.has(item.socketId) &&
-        item.socketId !== getSocketId()
-      ) {
-        hooksRtcMap.value.add(
-          await startNewWebRtc({ receiver: item.socketId })
-        );
-        await addTransceiver();
+  async function batchSendOffer(socketId: string) {
+    await nextTick(async () => {
+      console.log('batchSendOffer', offerSended.value, liveUserList.value);
+      console.log(socketId, 2222222);
+      if (!offerSended.value.has(socketId) && socketId !== getSocketId()) {
+        console.log('kkkkkk', socketId);
+        hooksRtcMap.value.add(await startNewWebRtc({ receiver: socketId }));
+        await addTransceiver(socketId);
         console.warn('new WebRTCClass完成');
         console.log('执行sendOffer', {
           sender: getSocketId(),
-          receiver: item.socketId,
+          receiver: socketId,
         });
-        sendOffer({ sender: getSocketId(), receiver: item.socketId });
-        offerSended.value.add(item.socketId);
+        sendOffer({ sender: getSocketId(), receiver: socketId });
+        offerSended.value.add(socketId);
       }
     });
   }
 
   function addVideo() {
-    liveUserList.value.forEach(async (item) => {
-      if (item.socketId === sender.value) {
-        localVideoRef.value[sender.value].srcObject = localStream.value;
-      }
-      if (!offerSended.value.has(item.socketId)) {
-        hooksRtcMap.value.add(
-          await startNewWebRtc({
+    sidebarList.value.push({ socketId: getSocketId() });
+    nextTick(() => {
+      liveUserList.value.forEach(async (item) => {
+        if (item.socketId === getSocketId()) {
+          localVideoRef.value[getSocketId()].srcObject = localStream.value;
+        }
+        if (!offerSended.value.has(item.socketId)) {
+          hooksRtcMap.value.add(
+            await startNewWebRtc({
+              receiver: item.socketId,
+              videoEl: localVideoRef.value[item.socketId],
+              // videoEl: localVideoRef.value[sender.value],
+            })
+          );
+          await addTransceiver(item.socketId);
+          console.warn('new WebRTCClass完成');
+          console.log('执行sendOffer', {
+            sender: getSocketId(),
             receiver: item.socketId,
-            // videoEl: localVideoRef.value[item.socketId],
-            videoEl: localVideoRef.value[sender.value],
-          })
-        );
-        await addTransceiver();
-        console.warn('new WebRTCClass完成');
-        console.log('执行sendOffer', {
-          sender: getSocketId(),
-          receiver: item.socketId,
-        });
-        sendOffer({ sender: getSocketId(), receiver: item.socketId });
-        offerSended.value.add(item.socketId);
-      }
+          });
+          sendOffer({ sender: getSocketId(), receiver: item.socketId });
+          offerSended.value.add(item.socketId);
+        }
+      });
     });
   }
 
@@ -393,11 +393,11 @@ export function usePull({
     // websocket连接成功
     instance.socketIo.on(WsConnectStatusEnum.connect, () => {
       console.log('【websocket】websocket连接成功');
+      handleHeartbeat();
       if (!instance) return;
       instance.status = WsConnectStatusEnum.connect;
       instance.update();
       sendJoin();
-      handleHeartbeat();
     });
 
     // websocket连接断开
@@ -409,21 +409,26 @@ export function usePull({
     });
 
     // 收到offer
-    instance.socketIo.on(WsMsgTypeEnum.offer, (data: IOffer) => {
-      console.warn('【websocket】收到offer', data);
+    instance.socketIo.on(WsMsgTypeEnum.offer, async (data: IOffer) => {
+      console.warn(
+        '【websocket】收到offer',
+        `发送者:${data.data.sender},接收者:${data.data.receiver}`,
+        data
+      );
       if (isSRS) return;
       if (!instance) return;
       if (data.data.receiver === getSocketId()) {
-        sidebarList.value.push({ socketId: data.data.sender });
-        nextTick(async () => {
-          console.log(
-            '收到offer,这个offer是发给我的111',
-            localVideoRef.value[data.data.sender]
-          );
+        if (!data.isAdmin) {
+          sidebarList.value.push({ socketId: data.data.sender });
+        }
+        await nextTick(async () => {
+          console.log('收到offer,这个offer是发给我的');
           sender.value = data.data.sender;
           const rtc = await startNewWebRtc({
             receiver: data.data.sender,
-            videoEl: localVideoRef.value[data.data.sender],
+            videoEl: data.isAdmin
+              ? remoteVideoRef.value
+              : localVideoRef.value[data.data.sender],
           });
           if (rtc) {
             await rtc.setRemoteDescription(data.data.sdp);
@@ -431,7 +436,11 @@ export function usePull({
             await rtc.setLocalDescription(sdp);
             instance.send({
               msgType: WsMsgTypeEnum.answer,
-              data: { sdp, sender: getSocketId(), receiver: data.data.sender },
+              data: {
+                sdp,
+                sender: getSocketId(),
+                receiver: data.data.sender,
+              },
             });
           }
         });
@@ -464,8 +473,8 @@ export function usePull({
       if (!instance) return;
       const rtc = networkStore.getRtcMap(`${roomId.value}___${data.socketId}`);
       if (!rtc) return;
-      if (data.socketId !== getSocketId()) {
-        console.log('发的candidate');
+      if (data.data.receiver === getSocketId()) {
+        console.log('是发给我的candidate');
         const candidate = new RTCIceCandidate({
           sdpMid: data.data.sdpMid,
           sdpMLineIndex: data.data.sdpMLineIndex,
@@ -480,7 +489,7 @@ export function usePull({
             console.error('candidate失败', err);
           });
       } else {
-        console.log('是发的candidate');
+        console.log('是发给我的candidate');
       }
     });
 
@@ -507,6 +516,7 @@ export function usePull({
         avatar: 'red',
         socketId: item.id,
       }));
+      // batchSendOffer();
     });
 
     // 收到用户发送消息
@@ -546,6 +556,7 @@ export function usePull({
         msg: '',
       };
       damuList.value.push(danmu);
+      batchSendOffer(data.data.socketId);
     });
 
     // 用户离开房间

+ 21 - 4
src/hooks/use-push.ts

@@ -8,6 +8,7 @@ import {
   IAdminIn,
   ICandidate,
   IDanmu,
+  IJoin,
   ILiveUser,
   IOffer,
   MediaTypeEnum,
@@ -35,7 +36,7 @@ export function usePush({
   const router = useRouter();
   const userStore = useUserStore();
   const networkStore = useNetworkStore();
-
+  const heartbeatTimer = ref();
   const roomId = ref<string>(getRandomString(15));
   const danmuStr = ref('');
   const roomName = ref(getRandomString(5));
@@ -183,6 +184,17 @@ export function usePush({
     return dataURL;
   }
 
+  function handleHeartbeat(liveId: number) {
+    heartbeatTimer.value = setInterval(() => {
+      const instance = networkStore.wsMap.get(roomId.value);
+      if (!instance) return;
+      instance.send({
+        msgType: WsMsgTypeEnum.heartbeat,
+        data: { liveId },
+      });
+    }, 1000 * 5);
+  }
+
   function closeWs() {
     const instance = networkStore.wsMap.get(roomId.value);
     instance?.close();
@@ -244,7 +256,7 @@ export function usePush({
     await rtc.setLocalDescription(sdp);
     instance.send({
       msgType: WsMsgTypeEnum.offer,
-      data: { sdp, sender, receiver },
+      data: { sdp, sender, receiver, isAdmin: true },
     });
   }
 
@@ -297,7 +309,11 @@ export function usePush({
 
     // 收到offer
     instance.socketIo.on(WsMsgTypeEnum.offer, (data: IOffer) => {
-      console.warn('【websocket】收到offer', data);
+      console.warn(
+        '【websocket】收到offer',
+        `发送者:${data.data.sender},接收者:${data.data.receiver}`,
+        data
+      );
       if (isSRS) return;
       if (!instance) return;
       if (data.data.receiver === getSocketId()) {
@@ -397,8 +413,9 @@ export function usePush({
     });
 
     // 用户加入房间完成
-    instance.socketIo.on(WsMsgTypeEnum.joined, (data) => {
+    instance.socketIo.on(WsMsgTypeEnum.joined, (data: IJoin) => {
       console.log('【websocket】用户加入房间完成', data);
+      handleHeartbeat(data.data.liveId!);
       joined.value = true;
       liveUserList.value.push({
         socketId: `${getSocketId()}`,

+ 16 - 0
src/interface.ts

@@ -202,5 +202,21 @@ export interface ICandidate {
     candidate: string;
     sdpMid: string | null;
     sdpMLineIndex: number | null;
+    receiver: string;
+    sender: string;
+  };
+}
+
+export interface IJoin {
+  roomId: string;
+  socketId: string;
+  data: {
+    roomName: string;
+    coverImg: string;
+    userInfo?: IUser;
+    srs?: { streamurl: string; flvurl: string };
+    track: { audio: boolean; video: boolean };
+    liveId?: number;
   };
+  isAdmin?: boolean;
 }

+ 6 - 3
src/network/webRtc.ts

@@ -488,18 +488,21 @@ export class WebRTCClass {
       );
       this.rtcStatus.icecandidate = true;
       this.update();
-      if (event.candidate) {
+      if (event.candidate && !this.candidateFlag) {
         const networkStore = useNetworkStore();
         this.candidateFlag = true;
         this.update();
         console.log('准备发送candidate', event.candidate.candidate);
+        const roomId = this.roomId.split('___')[0];
+        console.log(this.roomId, networkStore.wsMap.get(roomId)?.socketIo?.id);
+        const receiver = this.roomId.split('___')[1];
         const data = {
           candidate: event.candidate.candidate,
           sdpMid: event.candidate.sdpMid,
           sdpMLineIndex: event.candidate.sdpMLineIndex,
-          // sender: networkStore.wsMap.get(this.roomId)?.socketIo?.id,
+          sender: networkStore.wsMap.get(roomId)?.socketIo?.id,
+          receiver,
         };
-        const roomId = this.roomId.split('___')[0];
         networkStore.wsMap
           .get(roomId)
           ?.send({ msgType: WsMsgTypeEnum.candidate, data });

+ 2 - 1
src/network/webSocket.ts

@@ -76,14 +76,15 @@ export class WebSocketClass {
 
   // 发送websocket消息
   send = ({ msgType, data }: { msgType: WsMsgTypeEnum; data?: any }) => {
-    console.log('【websocket】发送websocket消息', msgType, data);
     if (!this.socketIo?.connected) {
       console.error(
         '【websocket】未连接成功,不发送websocket消息!',
         msgType,
         data
       );
+      return;
     }
+    console.log('【websocket】发送websocket消息', msgType, data);
     this.socketIo?.emit(msgType, {
       roomId: this.roomId,
       socketId: this.socketIo.id,

+ 1 - 0
src/views/meeting/index.vue

@@ -436,6 +436,7 @@ onMounted(() => {
       .list {
         margin-bottom: 10px;
         height: 300px;
+        overflow: scroll;
         .item {
           margin-bottom: 10px;
           font-size: 12px;

+ 4 - 0
src/views/pull/index.vue

@@ -56,9 +56,11 @@
                 x5-video-orientation="portraint"
                 muted
               ></video>
+              <div>{{ item.socketId }}</div>
             </div>
 
             <div
+              v-if="showJoin"
               class="join"
               @click="handleJoin()"
             >
@@ -172,6 +174,7 @@ const route = useRoute();
 const userStore = useUserStore();
 const appStore = useAppStore();
 
+const showJoin = ref(true);
 const topRef = ref<HTMLDivElement>();
 const bottomRef = ref<HTMLDivElement>();
 const containerRef = ref<HTMLDivElement>();
@@ -207,6 +210,7 @@ const {
 });
 
 function handleJoin() {
+  showJoin.value = !showJoin.value;
   nextTick(async () => {
     // await startGetDisplayMedia();
     await startGetUserMedia();

+ 3 - 0
src/views/push/index.vue

@@ -66,6 +66,7 @@
               x5-video-orientation="portraint"
               muted
             ></video>
+            <div>{{ item.socketId }}</div>
           </div>
         </div>
       </div>
@@ -437,6 +438,8 @@ onMounted(() => {
       .list {
         margin-bottom: 10px;
         height: 300px;
+        overflow: scroll;
+
         .item {
           margin-bottom: 10px;
           font-size: 12px;