shuisheng před 1 rokem
rodič
revize
738dc3f0b5

+ 6 - 0
src/App.vue

@@ -6,6 +6,12 @@
   </n-config-provider>
 </template>
 
+<script lang="ts">
+export default {
+  name: 'MainApp',
+};
+</script>
+
 <script lang="ts" setup>
 import { isMobile } from 'billd-utils';
 import { GlobalThemeOverrides, NConfigProvider } from 'naive-ui';

+ 1 - 0
src/components/FullLoading/main.vue

@@ -18,6 +18,7 @@
 import { StyleValue, defineComponent, ref } from 'vue';
 
 export default defineComponent({
+  name: 'fullLoading',
   setup() {
     const isFixed = ref(false);
     const loading = ref(false);

+ 6 - 0
src/components/Message/index.vue

@@ -4,6 +4,12 @@
   </NMessageProvider>
 </template>
 
+<script lang="ts">
+export default {
+  name: 'naiveuiMessage',
+};
+</script>
+
 <script lang="ts" setup>
 import { NMessageProvider } from 'naive-ui';
 

+ 1 - 0
src/constant.ts

@@ -186,6 +186,7 @@ export const mediaTypeEnumMap = {
   [MediaTypeEnum.time]: '时间',
   [MediaTypeEnum.stopwatch]: '秒表',
   [MediaTypeEnum.pk]: '打pk',
+  [MediaTypeEnum.metting]: '会议',
 };
 
 export const sliderList = [

+ 1 - 0
src/hooks/loginModal/index.vue

@@ -29,6 +29,7 @@ import { defineComponent, ref } from 'vue';
 import { useQQLogin } from '@/hooks/use-login';
 
 export default defineComponent({
+  name: 'loginModal',
   setup() {
     const title = ref('登录');
     const show = ref(false);

+ 1 - 0
src/hooks/modal/index.vue

@@ -36,6 +36,7 @@
 import { VNode, defineComponent, ref, render, watch } from 'vue';
 
 export default defineComponent({
+  name: 'modal',
   emits: ['ok', 'cancel'],
   setup() {
     const title = ref('');

+ 13 - 2
src/hooks/use-pull.ts

@@ -201,7 +201,18 @@ export function usePull(roomId: string) {
     () => roomLiving.value,
     (val) => {
       if (val) {
-        if (appStore.liveRoomInfo?.type !== LiveRoomTypeEnum.user_wertc) {
+        if (
+          appStore.liveRoomInfo &&
+          [
+            LiveRoomTypeEnum.system,
+            LiveRoomTypeEnum.user_msr,
+            LiveRoomTypeEnum.user_srs,
+            LiveRoomTypeEnum.user_obs,
+            LiveRoomTypeEnum.user_pk,
+            LiveRoomTypeEnum.user_tencent_css,
+            LiveRoomTypeEnum.user_tencent_css_pk,
+          ].includes(appStore.liveRoomInfo.type!)
+        ) {
           handlePlay(appStore.liveRoomInfo!);
         }
       } else {
@@ -403,7 +414,7 @@ export function usePull(roomId: string) {
 
   function closeRtc() {
     networkStore.rtcMap.forEach((rtc) => {
-      networkStore.removeRtc(rtc.roomId);
+      networkStore.removeRtc(rtc.receiver);
     });
   }
 

+ 1 - 3
src/hooks/use-push.ts

@@ -74,7 +74,7 @@ export function usePush() {
 
   function closeRtc() {
     networkStore.rtcMap.forEach((rtc) => {
-      networkStore.removeRtc(rtc.roomId);
+      networkStore.removeRtc(rtc.receiver);
     });
   }
 
@@ -90,8 +90,6 @@ export function usePush() {
       });
       console.log('新的allTrack音频轨', mixedStream.getAudioTracks());
       console.log('新的allTrack视频轨', mixedStream.getVideoTracks());
-      console.log('旧的allTrack音频轨', localStream.value?.getAudioTracks());
-      console.log('旧的allTrack视频轨', localStream.value?.getVideoTracks());
       // localStream.value = mixedStream;
     },
     { deep: true }

+ 4 - 0
src/hooks/use-rtcParams.ts

@@ -133,6 +133,10 @@ export const useRTCParams = () => {
         type: MediaTypeEnum.stopwatch,
         txt: '秒表',
       },
+      [MediaTypeEnum.metting]: {
+        type: MediaTypeEnum.metting,
+        txt: '会议',
+      },
     };
 
   return { maxBitrate, maxFramerate, resolutionRatio, allMediaTypeList };

+ 85 - 205
src/hooks/use-websocket.ts

@@ -77,7 +77,7 @@ export const useWebsocket = () => {
     clearInterval(loopGetLiveUserTimer.value);
   });
 
-  function createVideo2() {
+  function createNullVideo() {
     const videoEl = document.createElement('video');
     videoEl.autoplay = true;
     videoEl.muted = true;
@@ -241,7 +241,6 @@ export const useWebsocket = () => {
         videoEl,
         sender,
         receiver,
-        localStream: canvasVideoStream.value,
       });
     },
     /**
@@ -265,182 +264,81 @@ export const useWebsocket = () => {
           isAnchor: true,
           sender,
           receiver,
-          videoEl: createVideo({
-            appendChild: true,
-          }),
+          videoEl: createNullVideo(),
         });
-        canvasVideoStream.value?.getTracks().forEach((track) => {
-          if (canvasVideoStream.value) {
-            console.log(
-              'nativeWebRtc的canvasVideoStream插入track',
-              track.kind,
-              track
-            );
-            rtc.peerConnection?.addTrack(track, canvasVideoStream.value);
-          }
-        });
-        const offerSdp = await rtc.createOffer();
-        if (!offerSdp) {
-          console.error('nativeWebRtc的offerSdp为空');
-          return;
-        }
-        await rtc.setLocalDescription(offerSdp!);
-        networkStore.wsMap.get(roomId.value)?.send<WsOfferType['data']>({
-          requestId: getRandomString(8),
-          msgType: WsMsgTypeEnum.nativeWebRtcOffer,
-          data: {
-            live_room: appStore.liveRoomInfo!,
-            live_room_id: appStore.liveRoomInfo!.id!,
-            sender,
-            receiver,
-            sdp: offerSdp,
-          },
-        });
-      } catch (error) {
-        console.error('nativeWebRtc的sendOffer错误');
-      }
-    },
-    /**
-     * 原生webrtc视频通话
-     * 用户收到房主的offer,用户回复房主answer
-     */
-    sendAnswer: async ({
-      isPk,
-      sdp,
-      sender,
-      receiver,
-    }: {
-      isPk: boolean;
-      sdp: RTCSessionDescriptionInit;
-      sender: string;
-      receiver: string;
-    }) => {
-      console.log('开始nativeWebRtc的sendAnswer', { sender, receiver, sdp });
-      try {
-        const ws = networkStore.wsMap.get(roomId.value);
-        if (!ws) return;
-        const rtc = networkStore.rtcMap.get(receiver);
-        if (rtc) {
-          await rtc.setRemoteDescription(sdp);
-          if (isPk) {
-            if (!isAnchor.value) {
-              const stream = await handleUserMedia({
-                video: true,
-                audio: true,
-              });
-              if (rtc?.peerConnection) {
-                rtc.peerConnection.onnegotiationneeded = (event) => {
-                  console.log('onnegotiationneeded', event);
-                };
-                stream?.getTracks().forEach((track) => {
-                  rtc.peerConnection?.addTrack(track, stream);
+        if (
+          appStore.liveRoomInfo?.type === LiveRoomTypeEnum.user_wertc_meeting
+        ) {
+          dialog.warning({
+            title: '提示',
+            content: '是否加入会议',
+            positiveText: '确认',
+            onPositiveClick() {
+              async function main() {
+                const stream = await handleUserMedia({
+                  video: true,
+                  audio: true,
                 });
+                if (rtc?.peerConnection) {
+                  stream?.getTracks().forEach((track) => {
+                    console.log('加入会议插入track', track.kind, track);
+                    rtc.peerConnection?.addTrack(track, stream);
+                  });
+                }
+                const offerSdp = await rtc.createOffer();
+                if (!offerSdp) {
+                  console.error('nativeWebRtc的offerSdp为空');
+                  return;
+                }
+                await rtc.setLocalDescription(offerSdp!);
+                networkStore.wsMap
+                  .get(roomId.value)
+                  ?.send<WsOfferType['data']>({
+                    requestId: getRandomString(8),
+                    msgType: WsMsgTypeEnum.nativeWebRtcOffer,
+                    data: {
+                      live_room: appStore.liveRoomInfo!,
+                      live_room_id: appStore.liveRoomInfo!.id!,
+                      sender,
+                      receiver,
+                      sdp: offerSdp,
+                    },
+                  });
               }
+              return main();
+            },
+          });
+        } else if (
+          appStore.liveRoomInfo?.type === LiveRoomTypeEnum.user_wertc
+        ) {
+          canvasVideoStream.value?.getTracks().forEach((track) => {
+            if (canvasVideoStream.value) {
+              console.log(
+                'nativeWebRtc的canvasVideoStream插入track',
+                track.kind,
+                track
+              );
+              rtc.peerConnection?.addTrack(track, canvasVideoStream.value);
             }
-          }
-          const answerSdp = await rtc.createAnswer();
-          if (!answerSdp) {
-            console.error('nativeWebRtc的answerSdp为空');
+          });
+          const offerSdp = await rtc.createOffer();
+          if (!offerSdp) {
+            console.error('nativeWebRtc的offerSdp为空');
             return;
           }
-          await rtc.setLocalDescription(answerSdp);
-          networkStore.wsMap.get(roomId.value)?.send<WsAnswerType['data']>({
+          await rtc.setLocalDescription(offerSdp!);
+          networkStore.wsMap.get(roomId.value)?.send<WsOfferType['data']>({
             requestId: getRandomString(8),
-            msgType: WsMsgTypeEnum.nativeWebRtcAnswer,
+            msgType: WsMsgTypeEnum.nativeWebRtcOffer,
             data: {
-              live_room_id: Number(roomId.value),
+              live_room: appStore.liveRoomInfo!,
+              live_room_id: appStore.liveRoomInfo!.id!,
               sender,
               receiver,
-              sdp: answerSdp,
+              sdp: offerSdp,
             },
           });
-        } else {
-          console.error('rtc不存在');
-        }
-      } catch (error) {
-        console.error('nativeWebRtc的sendAnswer错误');
-      }
-    },
-  };
-
-  const nativeWebRtcMeeting = {
-    newWebrtc: ({
-      isAnchor,
-      sender,
-      receiver,
-      videoEl,
-    }: {
-      isAnchor: boolean;
-      sender: string;
-      receiver: string;
-      videoEl: HTMLVideoElement;
-    }) => {
-      return new WebRTCClass({
-        maxBitrate: currentMaxBitrate.value,
-        maxFramerate: currentMaxFramerate.value,
-        resolutionRatio: currentResolutionRatio.value,
-        isSRS: false,
-        roomId: roomId.value,
-        isAnchor,
-        videoEl,
-        sender,
-        receiver,
-        localStream: canvasVideoStream.value,
-      });
-    },
-    /**
-     * 原生webrtc视频通话
-     * 视频发起方是房主,房主发offer给用户
-     */
-    sendOffer: async ({
-      sender,
-      receiver,
-    }: {
-      sender: string;
-      receiver: string;
-    }) => {
-      console.log('开始nativeWebRtc的sendOffer', { sender, receiver });
-      try {
-        const ws = networkStore.wsMap.get(roomId.value);
-        if (!ws) return;
-        if (networkStore.rtcMap.get(receiver)) {
-          return;
         }
-        const rtc = nativeWebRtc.newWebrtc({
-          isAnchor: true,
-          sender,
-          receiver,
-          videoEl: createVideo({
-            appendChild: true,
-          }),
-        });
-        canvasVideoStream.value?.getTracks().forEach((track) => {
-          if (rtc && canvasVideoStream.value) {
-            console.log(
-              'nativeWebRtc的canvasVideoStream插入track',
-              track.kind,
-              track
-            );
-            rtc.peerConnection?.addTrack(track, canvasVideoStream.value);
-          }
-        });
-        const offerSdp = await rtc.createOffer();
-        if (!offerSdp) {
-          console.error('nativeWebRtc的offerSdp为空');
-          return;
-        }
-        await rtc.setLocalDescription(offerSdp!);
-        networkStore.wsMap.get(roomId.value)?.send<WsOfferType['data']>({
-          requestId: getRandomString(8),
-          msgType: WsMsgTypeEnum.nativeWebRtcOffer,
-          data: {
-            live_room: appStore.liveRoomInfo!,
-            live_room_id: Number(roomId.value),
-            sender,
-            receiver,
-            sdp: offerSdp,
-          },
-        });
       } catch (error) {
         console.error('nativeWebRtc的sendOffer错误');
       }
@@ -528,7 +426,6 @@ export const useWebsocket = () => {
         isSRS: true,
         sender,
         receiver: 'srs',
-        localStream: canvasVideoStream.value,
       });
     },
     /**
@@ -652,7 +549,7 @@ export const useWebsocket = () => {
         console.log('收到srsOffer', data);
         if (data.receiver === mySocketId.value) {
           console.warn('是发给我的srsOffer');
-          const videoEl = createVideo2();
+          const videoEl = createNullVideo();
           const rtc = new WebRTCClass({
             isAnchor: true,
             maxBitrate: currentMaxBitrate.value,
@@ -693,7 +590,7 @@ export const useWebsocket = () => {
       console.log('收到srsAnswer', data);
       if (data.receiver === mySocketId.value) {
         console.warn('是发给我的srsAnswer');
-        const rtc = networkStore.getRtcMap(data.sender);
+        const rtc = networkStore.rtcMap.get(data.sender);
         rtc?.setRemoteDescription(data.sdp);
       } else {
         console.error('不是发给我的srsAnswer');
@@ -707,7 +604,7 @@ export const useWebsocket = () => {
         console.log('收到srsCandidate', data);
         if (data.receiver === mySocketId.value) {
           console.warn('是发给我的srsCandidate');
-          const rtc = networkStore.getRtcMap(data.sender);
+          const rtc = networkStore.rtcMap.get(data.sender);
           rtc?.addIceCandidate(data.candidate);
         } else {
           console.error('不是发给我的srsCandidate');
@@ -741,9 +638,7 @@ export const useWebsocket = () => {
                         // 但是这里的nativeWebRtc的sender,得是自己,不能是data.data.sender,不要混淆
                         sender: mySocketId.value,
                         receiver: data.sender,
-                        videoEl: createVideo({
-                          appendChild: true,
-                        }),
+                        videoEl: createNullVideo(),
                       });
                       nativeWebRtc.sendAnswer({
                         isPk: true,
@@ -771,7 +666,7 @@ export const useWebsocket = () => {
                 // 但是这里的nativeWebRtc的sender,得是自己,不能是data.data.sender,不要混淆
                 sender: mySocketId.value,
                 receiver: data.sender,
-                videoEl: createVideo2(),
+                videoEl: createNullVideo(),
               });
               nativeWebRtc.sendAnswer({
                 isPk: true,
@@ -793,7 +688,7 @@ export const useWebsocket = () => {
               // 但是这里的nativeWebRtc的sender,得是自己,不能是data.data.sender,不要混淆
               sender: mySocketId.value,
               receiver: data.sender,
-              videoEl: createVideo2(),
+              videoEl: createNullVideo(),
             });
             await nativeWebRtc.sendAnswer({
               isPk: false,
@@ -806,7 +701,6 @@ export const useWebsocket = () => {
             console.error('不是发给我的nativeWebRtcOffer');
           }
         }
-        return '1';
       }
     );
 
@@ -817,7 +711,7 @@ export const useWebsocket = () => {
         console.log('收到nativeWebRtcAnswer', data);
         if (data.receiver === mySocketId.value) {
           console.warn('是发给我的nativeWebRtcAnswer');
-          const rtc = networkStore.getRtcMap(data.sender);
+          const rtc = networkStore.rtcMap.get(data.sender);
           if (rtc) {
             await rtc.setRemoteDescription(data.sdp);
           }
@@ -834,7 +728,7 @@ export const useWebsocket = () => {
         console.log('收到nativeWebRtcCandidate', data);
         if (data.receiver === mySocketId.value) {
           console.warn('是发给我的nativeWebRtcCandidate');
-          const rtc = networkStore.getRtcMap(data.sender);
+          const rtc = networkStore.rtcMap.get(data.sender);
           rtc?.addIceCandidate(data.candidate);
         } else {
           console.error('不是发给我的nativeWebRtcCandidate');
@@ -851,14 +745,18 @@ export const useWebsocket = () => {
         if (data.anchor_socket_id) {
           anchorSocketId.value = data.anchor_socket_id;
         }
-        isSRS.value = true;
-        if (
-          data.live_room.type &&
-          [LiveRoomTypeEnum.user_wertc, LiveRoomTypeEnum.user_pk].includes(
-            data.live_room.type
-          )
-        ) {
-          isSRS.value = false;
+        if (route.name === routerName.pull) {
+          // 当前是拉流页面
+          if (data.live_room?.type === LiveRoomTypeEnum.user_wertc_meeting) {
+            data.socket_list?.forEach((item) => {
+              if (item !== mySocketId.value) {
+                nativeWebRtc.sendOffer({
+                  sender: mySocketId.value,
+                  receiver: item,
+                });
+              }
+            });
+          }
         }
       }
     );
@@ -999,27 +897,9 @@ export const useWebsocket = () => {
               });
             }
           });
-        } else {
-          data.socket_list.forEach((item) => {
-            if (item !== mySocketId.value) {
-              if (
-                [
-                  LiveRoomTypeEnum.user_wertc,
-                  LiveRoomTypeEnum.user_wertc_meeting,
-                  LiveRoomTypeEnum.user_pk,
-                ].includes(data.live_room.type!)
-              ) {
-                isSRS.value = false;
-                nativeWebRtc.sendOffer({
-                  sender: mySocketId.value,
-                  receiver: item,
-                });
-              }
-            }
-          });
         }
       } else {
-        //  当前不是推流页面
+        // 当前不是推流页面
       }
     });
 
@@ -1034,7 +914,7 @@ export const useWebsocket = () => {
       if (anchorSocketId.value === data.socket_id) {
         roomLiving.value = false;
       }
-      networkStore.removeRtc(`${roomId.value}`);
+      networkStore.removeRtc(data.socket_id);
       damuList.value.push({
         live_room_id: Number(roomId.value),
         socket_id: data.socket_id,

+ 2 - 0
src/interface.ts

@@ -510,6 +510,7 @@ export interface ILive extends ISrsPublishStream {
   updated_at?: string;
   deleted_at?: string;
 }
+
 export enum MediaTypeEnum {
   camera,
   screen,
@@ -521,6 +522,7 @@ export enum MediaTypeEnum {
   stopwatch,
   webAudio,
   pk,
+  metting,
 }
 
 export enum DanmuMsgTypeEnum {

+ 216 - 196
src/network/webRTC.ts

@@ -34,6 +34,7 @@ export async function handleResolutionRatio(data: {
     return 0;
   }
 }
+
 /** 设置帧率 */
 export async function handleMaxFramerate(data: {
   frameRate: number;
@@ -45,7 +46,6 @@ export async function handleMaxFramerate(data: {
   console.log('开始设置帧率', frameRate);
   stream.getTracks().forEach((track) => {
     if (track.kind === 'video') {
-      console.log('开始设置帧率---', frameRate, track.id);
       queue.push(
         track.applyConstraints({
           height: { ideal: height },
@@ -118,109 +118,14 @@ export class WebRTCClass {
     this.createPeerConnection();
   }
 
-  prettierLog = (msg: string, type?: 'log' | 'warn' | 'error', ...args) => {
+  prettierLog = (data: { msg: string; type?: 'log' | 'warn' | 'error' }) => {
+    const { msg, type } = data;
     console[type || 'log'](
-      `${new Date().toLocaleString()},${this.roomId},${msg}`,
-      ...args
+      `【WebRTCClass】${new Date().toLocaleString()},房间id:${this.roomId}`,
+      msg
     );
   };
 
-  addTrack = (stream: MediaStream, isCb?: boolean) => {
-    console.log('开始addTrack,是否是pc的track回调', isCb);
-    console.log('收到新track', stream);
-    console.log('收到新track的视频轨', stream.getVideoTracks());
-    console.log('收到新track的音频轨', stream.getAudioTracks());
-    console.log('原本旧track的视频轨', this.localStream?.getVideoTracks());
-    console.log('原本旧track的音频轨', this.localStream?.getAudioTracks());
-
-    const appStore = useAppStore();
-    if (isCb) {
-      stream.onremovetrack = (event) => {
-        console.log('onremovetrack事件', event);
-        const res = appStore.allTrack.filter((info) => {
-          if (info.track?.id === event.track.id) {
-            return false;
-          }
-          return true;
-        });
-        appStore.setAllTrack(res);
-      };
-    }
-
-    const addTrack: AppRootState['allTrack'] = [];
-
-    this.localStream?.getVideoTracks().forEach((track) => {
-      if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
-        addTrack.push({
-          openEye: true,
-          id: getRandomString(8),
-          track,
-          stream,
-          audio: 2,
-          video: 1,
-          type: MediaTypeEnum.screen,
-          mediaName: '',
-          streamid: stream.id,
-          trackid: track.id,
-          scaleInfo: {},
-        });
-      }
-    });
-    this.localStream?.getAudioTracks().forEach((track) => {
-      if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
-        addTrack.push({
-          openEye: true,
-          id: getRandomString(8),
-          track,
-          stream,
-          audio: 1,
-          video: 2,
-          type: MediaTypeEnum.microphone,
-          mediaName: '',
-          streamid: stream.id,
-          trackid: track.id,
-          scaleInfo: {},
-        });
-      }
-    });
-    stream.getVideoTracks().forEach((track) => {
-      if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
-        addTrack.push({
-          openEye: true,
-          id: getRandomString(8),
-          track,
-          stream,
-          audio: 2,
-          video: 1,
-          type: MediaTypeEnum.screen,
-          mediaName: '',
-          streamid: stream.id,
-          trackid: track.id,
-          scaleInfo: {},
-        });
-      }
-    });
-    stream.getAudioTracks().forEach((track) => {
-      if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
-        addTrack.push({
-          openEye: true,
-          id: getRandomString(8),
-          track,
-          stream,
-          audio: 1,
-          video: 2,
-          type: MediaTypeEnum.microphone,
-          mediaName: '',
-          streamid: stream.id,
-          trackid: track.id,
-          scaleInfo: {},
-        });
-      }
-    });
-    // this.localStream = stream;
-    appStore.pkStream = stream;
-  };
-
   /** 设置分辨率 */
   setResolutionRatio = async (height: number) => {
     if (this.localStream) {
@@ -229,7 +134,6 @@ export class WebRTCClass {
         stream: this.localStream,
         height,
       });
-      console.log(res, '设置分辨率');
       return res;
     }
   };
@@ -242,7 +146,6 @@ export class WebRTCClass {
         stream: this.localStream,
         height: this.resolutionRatio,
       });
-      console.log(res, '设置最大帧率');
       return res;
     }
     // return new Promise<number>((resolve) => {
@@ -305,68 +208,68 @@ export class WebRTCClass {
     });
   };
 
-  // 创建offer
+  /** 创建offer */
   createOffer = async () => {
     if (!this.peerConnection) return;
-    this.prettierLog('createOffer开始', 'warn');
+    this.prettierLog({ msg: 'createOffer开始', type: 'warn' });
     try {
       const sdp = await this.peerConnection.createOffer();
-      this.prettierLog('createOffer成功', 'warn', sdp);
+      this.prettierLog({ msg: 'createOffer成功', type: 'warn' });
       return sdp;
     } catch (error) {
-      this.prettierLog('createOffer失败', 'error');
-      console.log(error);
+      this.prettierLog({ msg: 'createOffer失败', type: 'error' });
+      console.error(error);
     }
   };
 
-  addIceCandidate = async (candidate: RTCIceCandidateInit) => {
+  /** 创建answer */
+  createAnswer = async () => {
+    if (!this.peerConnection) return;
+    this.prettierLog({ msg: 'createAnswer开始', type: 'warn' });
     try {
-      await this.peerConnection?.addIceCandidate(candidate);
-      console.log('addIceCandidate成功');
+      const sdp = await this.peerConnection.createAnswer();
+      this.prettierLog({ msg: 'createAnswer成功', type: 'warn' });
+      return sdp;
     } catch (error) {
-      console.error('addIceCandidate错误');
-      console.log(error);
+      this.prettierLog({ msg: 'createAnswer失败', type: 'error' });
+      console.error(error);
     }
   };
 
-  // 创建answer
-  createAnswer = async () => {
-    if (!this.peerConnection) return;
-    this.prettierLog('createAnswer开始', 'warn');
+  /** 处理candidate */
+  addIceCandidate = async (candidate: RTCIceCandidateInit) => {
+    this.prettierLog({ msg: 'addIceCandidate开始', type: 'warn' });
     try {
-      const sdp = await this.peerConnection.createAnswer();
-      this.prettierLog('createAnswer成功', 'warn', sdp);
-      return sdp;
+      await this.peerConnection?.addIceCandidate(candidate);
+      this.prettierLog({ msg: 'addIceCandidate成功', type: 'warn' });
     } catch (error) {
-      this.prettierLog('createAnswer失败', 'error');
-      console.log(error);
+      this.prettierLog({ msg: 'addIceCandidate错误', type: 'error' });
+      console.error(error);
     }
   };
 
-  // 设置本地描述
+  /** 设置本地描述 */
   setLocalDescription = async (sdp: RTCLocalSessionDescriptionInit) => {
     if (!this.peerConnection) return;
-    this.prettierLog('setLocalDescription开始', 'warn');
+    this.prettierLog({ msg: 'setLocalDescription开始', type: 'warn' });
     try {
       await this.peerConnection.setLocalDescription(sdp);
-      this.prettierLog('setLocalDescription成功', 'warn', sdp);
+      this.prettierLog({ msg: 'setLocalDescription成功', type: 'warn' });
     } catch (error) {
-      this.prettierLog('setLocalDescription失败', 'error');
-      console.error('setLocalDescription', sdp);
+      this.prettierLog({ msg: 'setLocalDescription失败', type: 'error' });
       console.error(error);
     }
   };
 
-  // 设置远端描述
+  /** 设置远端描述 */
   setRemoteDescription = async (sdp: RTCSessionDescriptionInit) => {
     if (!this.peerConnection) return;
-    this.prettierLog(`setRemoteDescription开始`, 'warn');
+    this.prettierLog({ msg: 'setRemoteDescription开始', type: 'warn' });
     try {
       await this.peerConnection.setRemoteDescription(sdp);
-      this.prettierLog('setRemoteDescription成功', 'warn', sdp);
+      this.prettierLog({ msg: 'setRemoteDescription成功', type: 'warn' });
     } catch (error) {
-      this.prettierLog('setRemoteDescription失败', 'error');
-      console.error('setRemoteDescription', sdp);
+      this.prettierLog({ msg: 'setRemoteDescription失败', type: 'error' });
       console.error(error);
     }
   };
@@ -374,21 +277,107 @@ export class WebRTCClass {
   handleStreamEvent = () => {
     if (!this.peerConnection) return;
     // 废弃:https://developer.mozilla.org/en-US/docs/Web/API/RTCPeerConnection/addStream
-    console.warn(`${this.roomId},开始监听pc的addstream`);
-    this.peerConnection.addEventListener('addstream', () => {
-      // console.warn(`${this.roomId},pc收到addstream事件`, event);
-      // console.log('addstream事件的stream', event.stream);
-      // console.log('addstream事件的视频轨', event.stream.getVideoTracks());
-      // console.log('addstream事件的音频轨', event.stream.getAudioTracks());
-    });
+    // this.prettierLog({ msg: '开始监听pc的addstream事件', type: 'warn' });
+    // this.peerConnection.addEventListener('addstream', (event) => {
+    //   this.prettierLog({ msg: 'pc收到addstream事件', type: 'warn' });
+    //   console.log('addstream事件的event', event);
+    //   console.log('addstream事件的stream', event.stream);
+    //   console.log('addstream事件的视频轨', event.stream.getVideoTracks());
+    //   console.log('addstream事件的音频轨', event.stream.getAudioTracks());
+    // });
 
-    console.warn(`${this.roomId},开始监听pc的track`);
+    this.prettierLog({ msg: '开始监听pc的track事件', type: 'warn' });
     this.peerConnection.addEventListener('track', (event) => {
-      console.warn(`${this.roomId},pc收到track事件`, event);
+      this.prettierLog({ msg: 'pc收到track事件', type: 'warn' });
+      console.log('track事件的event', event);
       console.log('track事件的stream', event.streams[0]);
       console.log('track事件的视频轨', event.streams[0].getVideoTracks());
       console.log('track事件的音频轨', event.streams[0].getAudioTracks());
-      this.addTrack(event.streams[0], true);
+
+      const stream = event.streams[0];
+      this.localStream = stream;
+      const appStore = useAppStore();
+      stream.onremovetrack = (event) => {
+        this.prettierLog({ msg: 'onremovetrack事件', type: 'warn' });
+        const res = appStore.allTrack.filter((info) => {
+          if (info.track?.id === event.track.id) {
+            return false;
+          }
+          return true;
+        });
+        appStore.setAllTrack(res);
+      };
+
+      const addTrack: AppRootState['allTrack'] = [];
+
+      this.localStream?.getVideoTracks().forEach((track) => {
+        if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
+          addTrack.push({
+            openEye: true,
+            id: getRandomString(8),
+            track,
+            stream,
+            audio: 2,
+            video: 1,
+            type: MediaTypeEnum.screen,
+            mediaName: '',
+            streamid: stream.id,
+            trackid: track.id,
+            scaleInfo: {},
+          });
+        }
+      });
+      this.localStream?.getAudioTracks().forEach((track) => {
+        if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
+          addTrack.push({
+            openEye: true,
+            id: getRandomString(8),
+            track,
+            stream,
+            audio: 1,
+            video: 2,
+            type: MediaTypeEnum.microphone,
+            mediaName: '',
+            streamid: stream.id,
+            trackid: track.id,
+            scaleInfo: {},
+          });
+        }
+      });
+      stream.getVideoTracks().forEach((track) => {
+        if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
+          addTrack.push({
+            openEye: true,
+            id: getRandomString(8),
+            track,
+            stream,
+            audio: 2,
+            video: 1,
+            type: MediaTypeEnum.screen,
+            mediaName: '',
+            streamid: stream.id,
+            trackid: track.id,
+            scaleInfo: {},
+          });
+        }
+      });
+      stream.getAudioTracks().forEach((track) => {
+        if (!appStore.allTrack.find((info) => info.track?.id === track.id)) {
+          addTrack.push({
+            openEye: true,
+            id: getRandomString(8),
+            track,
+            stream,
+            audio: 1,
+            video: 2,
+            type: MediaTypeEnum.microphone,
+            mediaName: '',
+            streamid: stream.id,
+            trackid: track.id,
+            scaleInfo: {},
+          });
+        }
+      });
       this.videoEl.srcObject = event.streams[0];
     });
   };
@@ -397,10 +386,9 @@ export class WebRTCClass {
     if (!this.peerConnection) return;
     const appStore = useAppStore();
 
-    console.warn(`${this.roomId},开始监听pc的icecandidate`);
-    // icecandidate
+    this.prettierLog({ msg: '开始监听pc的icecandidate事件', type: 'warn' });
     this.peerConnection.addEventListener('icecandidate', (event) => {
-      this.prettierLog('pc收到icecandidate', 'warn');
+      this.prettierLog({ msg: 'pc收到icecandidate', type: 'warn' });
       if (event.candidate) {
         const networkStore = useNetworkStore();
         console.log('准备发送candidate', event.candidate.candidate);
@@ -421,98 +409,129 @@ export class WebRTCClass {
       }
     });
 
-    console.warn(`${this.roomId},开始监听pc的iceconnectionstatechange`);
-    // iceconnectionstatechange
+    this.prettierLog({
+      msg: '开始监听pc的iceconnectionstatechange事件',
+      type: 'warn',
+    });
     this.peerConnection.addEventListener(
       'iceconnectionstatechange',
       (event: any) => {
+        this.prettierLog({
+          msg: 'pc收到iceconnectionstatechange:connected',
+          type: 'warn',
+        });
         // https://developer.mozilla.org/zh-CN/docs/Web/API/RTCPeerConnection/connectionState
         const iceConnectionState = event.currentTarget.iceConnectionState;
-        console.log(
-          this.roomId,
-          'pc收到iceconnectionstatechange',
-          // eslint-disable-next-line
-          `iceConnectionState:${iceConnectionState}`,
-          event
-        );
         if (iceConnectionState === 'connected') {
           // ICE 代理至少对每个候选发现了一个可用的连接,此时仍然会继续测试远程候选以便发现更优的连接。同时可能在继续收集候选。
-          console.warn(this.roomId, 'iceConnectionState:connected', event);
-          console.warn('webrtc连接成功!');
+          this.prettierLog({
+            msg: 'iceConnectionState:connected',
+            type: 'warn',
+          });
+          this.prettierLog({
+            msg: 'webrtc连接成功!',
+            type: 'warn',
+          });
+          console.log('sender', this.sender, 'receiver', this.receiver);
+          this.update();
         }
         if (iceConnectionState === 'completed') {
           // ICE 代理已经发现了可用的连接,不再测试远程候选。
-          console.warn(this.roomId, 'iceConnectionState:completed', event);
+          this.prettierLog({
+            msg: 'iceConnectionState:completed',
+            type: 'warn',
+          });
         }
         if (iceConnectionState === 'failed') {
           // ICE 候选测试了所有远程候选没有发现匹配的候选。也可能有些候选中发现了一些可用连接。
-          console.error(this.roomId, 'iceConnectionState:failed', event);
+          this.prettierLog({
+            msg: 'iceConnectionState:failed',
+            type: 'error',
+          });
         }
         if (iceConnectionState === 'disconnected') {
           // 测试不再活跃,这可能是一个暂时的状态,可以自我恢复。
-          console.error(this.roomId, 'iceConnectionState:disconnected', event);
+          this.prettierLog({
+            msg: 'iceConnectionState:disconnected',
+            type: 'error',
+          });
         }
         if (iceConnectionState === 'closed') {
           // ICE 代理关闭,不再应答任何请求。
-          console.error(this.roomId, 'iceConnectionState:closed', event);
+          this.prettierLog({
+            msg: 'iceConnectionState:closed',
+            type: 'error',
+          });
         }
       }
     );
 
-    console.warn(`${this.roomId},开始监听pc的connectionstatechange`);
-    // connectionstatechange
+    this.prettierLog({
+      msg: '开始监听pc的connectionstatechange事件',
+      type: 'warn',
+    });
     this.peerConnection.addEventListener(
       'connectionstatechange',
       (event: any) => {
         const connectionState = event.currentTarget.connectionState;
-        console.log(
-          this.roomId,
-          'pc收到connectionstatechange',
-          // eslint-disable-next-line
-          `connectionState:${connectionState}`,
-          event
-        );
+        this.prettierLog({
+          msg: 'pc收到connectionstatechange:connected',
+          type: 'warn',
+        });
         if (connectionState === 'connected') {
           // 表示每一个 ICE 连接要么正在使用(connected 或 completed 状态),要么已被关闭(closed 状态);并且,至少有一个连接处于 connected 或 completed 状态。
-          console.warn(this.roomId, 'connectionState:connected');
+          this.prettierLog({
+            msg: 'connectionState:connected',
+            type: 'warn',
+          });
           appStore.setLiveLine(LiveLineEnum.rtc);
-          if (this.maxBitrate !== -1) {
-            this.setMaxBitrate(this.maxBitrate);
-          }
-          if (this.maxFramerate !== -1) {
-            this.setMaxFramerate(this.maxFramerate);
-          }
-          if (this.resolutionRatio !== -1) {
-            this.setResolutionRatio(this.resolutionRatio);
-          }
-          console.log(
-            this.maxBitrate,
-            this.maxFramerate,
-            this.resolutionRatio,
-            '配置'
-          );
+          // if (this.maxBitrate !== -1) {
+          //   this.setMaxBitrate(this.maxBitrate);
+          // }
+          // if (this.maxFramerate !== -1) {
+          //   this.setMaxFramerate(this.maxFramerate);
+          // }
+          // if (this.resolutionRatio !== -1) {
+          //   this.setResolutionRatio(this.resolutionRatio);
+          // }
         }
         if (connectionState === 'disconnected') {
           // 表示至少有一个 ICE 连接处于 disconnected 状态,并且没有连接处于 failed、connecting 或 checking 状态。
-          console.error(this.roomId, 'connectionState:disconnected');
+          this.prettierLog({
+            msg: 'connectionState:disconnected',
+            type: 'error',
+          });
         }
         if (connectionState === 'closed') {
           // 表示 RTCPeerConnection 已关闭。
-          console.error(this.roomId, 'connectionState:closed');
+          this.prettierLog({
+            msg: 'connectionState:closed',
+            type: 'error',
+          });
         }
         if (connectionState === 'failed') {
           // 表示至少有一个 ICE 连接处于 failed 的状态。
-          console.error(this.roomId, 'connectionState:failed');
+          this.prettierLog({
+            msg: 'connectionState:failed',
+            type: 'error',
+          });
         }
       }
     );
-    // negotiationneeded
-    // this.peerConnection.addEventListener('negotiationneeded', (event: any) => {
-    //   console.log(this.roomId, 'pc收到negotiationneeded', event);
-    // });
+
+    this.prettierLog({
+      msg: '开始监听pc的negotiationneeded事件',
+      type: 'warn',
+    });
+    this.peerConnection.addEventListener('negotiationneeded', () => {
+      this.prettierLog({
+        msg: 'pc收到negotiationneeded',
+        type: 'warn',
+      });
+    });
   };
 
-  // 创建对等连接
+  /** 创建对等连接 */
   createPeerConnection = () => {
     if (!window.RTCPeerConnection) {
       console.error('当前环境不支持RTCPeerConnection!');
@@ -541,10 +560,10 @@ export class WebRTCClass {
     }
   };
 
-  // 手动关闭webrtc连接
+  /** 手动关闭webrtc连接 */
   close = () => {
     try {
-      this.prettierLog('手动关闭webrtc连接', 'warn');
+      this.prettierLog({ msg: '手动关闭webrtc连接', type: 'warn' });
       this.localStream?.getTracks().forEach((track) => {
         track.stop();
       });
@@ -553,11 +572,12 @@ export class WebRTCClass {
       this.peerConnection = null;
       this.videoEl.remove();
     } catch (error) {
-      console.error('手动关闭webrtc连接失败', error);
+      this.prettierLog({ msg: '手动关闭webrtc连接失败', type: 'error' });
+      console.error(error);
     }
   };
 
-  // 更新store
+  /** 更新store */
   update = () => {
     const networkStore = useNetworkStore();
     networkStore.updateRtcMap(this.receiver, this);

+ 1 - 0
src/network/webSocket.ts

@@ -11,6 +11,7 @@ import {
 export function prettierReceiveWsMsg(...arg) {
   console.warn('【websocket】收到消息', ...arg);
 }
+
 export function prettierSendWsMsg(data: {
   requestId: string;
   msgType: string;

+ 14 - 17
src/store/network/index.ts

@@ -24,21 +24,6 @@ export const useNetworkStore = defineStore('network', {
         this.wsMap.set(roomId, arg);
       }
     },
-    updateRtcMap(roomId: string, arg) {
-      const val = this.rtcMap.get(roomId);
-      if (val) {
-        this.rtcMap.set(roomId, { ...val, ...arg });
-      } else {
-        this.rtcMap.set(roomId, arg);
-      }
-    },
-    removeRtc(roomId: string) {
-      const old = this.rtcMap.get(roomId);
-      if (old) {
-        old.close();
-      }
-      this.rtcMap.delete(roomId);
-    },
     removeWs(roomId: string) {
       const old = this.wsMap.get(roomId);
       if (old) {
@@ -46,8 +31,20 @@ export const useNetworkStore = defineStore('network', {
       }
       this.wsMap.delete(roomId);
     },
-    getRtcMap(roomId: string) {
-      return this.rtcMap.get(roomId);
+    updateRtcMap(socketId: string, arg) {
+      const val = this.rtcMap.get(socketId);
+      if (val) {
+        this.rtcMap.set(socketId, { ...val, ...arg });
+      } else {
+        this.rtcMap.set(socketId, arg);
+      }
+    },
+    removeRtc(socketId: string) {
+      const old = this.rtcMap.get(socketId);
+      if (old) {
+        old.close();
+      }
+      this.rtcMap.delete(socketId);
     },
   },
 });

+ 4 - 4
src/types/ILiveRoom.ts

@@ -13,14 +13,14 @@ export enum LiveRoomUseCDNEnum {
 export enum LiveRoomTypeEnum {
   /** 系统推流 */
   system,
-  /** 主播使用webrtc推流,直播 */
-  user_wertc,
-  /** 主播使用webrtc推流,会议 */
-  user_wertc_meeting,
   /** 主播使用srs推流 */
   user_srs,
   /** 主播使用obs/ffmpeg推流 */
   user_obs,
+  /** 主播使用webrtc推流,直播 */
+  user_wertc,
+  /** 主播使用webrtc推流,会议 */
+  user_wertc_meeting,
   /** 主播使用msr推流 */
   user_msr,
   /** 主播打pk */

+ 2 - 1
src/types/websocket.ts

@@ -89,7 +89,6 @@ export interface IWsFormat<T> {
 export type WsUpdateJoinInfoType = IWsFormat<{
   live_room_id: number;
   track?: { audio: number; video: number };
-  rtmp_url?: string;
 }>;
 
 /** 直播pk秘钥 */
@@ -112,6 +111,7 @@ export type WsGetLiveUserType = IWsFormat<{
 export type WsRoomLivingType = IWsFormat<{
   live_room: ILiveRoom;
   anchor_socket_id: string;
+  socket_list?: string[];
 }>;
 
 /** 直播间没在直播 */
@@ -190,6 +190,7 @@ export type WsJoinType = IWsFormat<{
   live_room?: ILiveRoom;
   anchor_info?: IUser;
   user_info?: IUser;
+  socket_list?: string[];
 }>;
 
 /** 用户离开直播间 */

+ 2 - 2
src/views/pull/index.vue

@@ -473,7 +473,6 @@ const {
   mySocketId,
   videoHeight,
   videoLoading,
-  remoteVideo,
   roomLiving,
   damuList,
   liveUserList,
@@ -597,7 +596,7 @@ async function handleUserMedia({ video, audio }) {
 
 async function handlePk() {
   const stream = await handleUserMedia({ video: true, audio: true });
-  const rtc = networkStore.getRtcMap(`${roomId.value}`)!;
+  const rtc = networkStore.rtcMap.get(`${roomId.value}`)!;
   if (rtc?.peerConnection) {
     rtc.peerConnection.onnegotiationneeded = (event) => {
       console.log('onnegotiationneeded', event);
@@ -643,6 +642,7 @@ watch(
     }, 0);
   }
 );
+
 watch(
   () => appStore.liveRoomInfo,
   () => {

+ 120 - 39
src/views/push/index.vue

@@ -98,7 +98,7 @@
               <i class="ico"></i>
               <span>
                 正在观看:
-                {{ liveUserList.length - 1 }}
+                {{ liveUserList.length }}
               </span>
             </span>
           </div>
@@ -510,6 +510,7 @@ watch(
     }
   }
 );
+
 watch(
   () => currentMaxFramerate.value,
   () => {
@@ -541,6 +542,34 @@ watch(
   }
 );
 
+watch(
+  () => networkStore.rtcMap,
+  (newVal) => {
+    console.log('rtcMap变了');
+    newVal.forEach((item) => {
+      addMediaOk({
+        id: getRandomEnglishString(6),
+        openEye: true,
+        audio: 2,
+        video: 1,
+        mediaName: item.receiver,
+        type: MediaTypeEnum.metting,
+        track: item.localStream?.getVideoTracks()[0],
+        trackid: item.localStream?.getVideoTracks()[0].id,
+        stream: item.localStream || undefined,
+        streamid: item.localStream?.id,
+        hidden: false,
+        muted: false,
+        scaleInfo: {},
+      });
+    });
+  },
+  {
+    deep: true,
+    immediate: true,
+  }
+);
+
 watch(
   () => damuList.value.length,
   () => {
@@ -842,7 +871,7 @@ function handleMixedAudio() {
     gainNode.gain.value = (item.volume || 100) / 100;
     source.connect(gainNode);
     res.push({ source, gainNode });
-    console.log('混流', item.stream?.id, item.stream);
+    // console.log('混流', item.stream?.id, item.stream);
   });
   const destination = audioCtx.createMediaStreamDestination();
   res.forEach((item) => {
@@ -940,40 +969,56 @@ function autoCreateVideo({
   }
   videoEl.srcObject = stream;
   return new Promise<{
-    canvasDom: fabric.Image;
+    canvasDom: Raw<fabric.Image>;
     videoEl: HTMLVideoElement;
     scale: number;
   }>((resolve) => {
     videoEl.onloadedmetadata = () => {
-      const width = stream.getVideoTracks()[0].getSettings().width!;
-      const height = stream.getVideoTracks()[0].getSettings().height!;
-      const ratio = handleScale({ width, height });
-      videoEl.width = width;
-      videoEl.height = height;
-
-      const canvasDom = markRaw(
-        new fabric.Image(videoEl, {
-          top: rect?.top || 0,
-          left: rect?.left || 0,
-          width,
-          height,
-        })
-      );
-      console.log(
-        '初始化',
-        ratio,
-        canvasDom.width,
-        canvasDom.height,
-        width * ratio,
-        height * ratio,
-        canvasDom
-      );
-      handleMoving({ canvasDom, id });
-      handleScaling({ canvasDom, id });
-      canvasDom.scale(ratio / window.devicePixelRatio);
-      fabricCanvas.value!.add(canvasDom);
-
-      resolve({ canvasDom, scale: ratio, videoEl });
+      let canvasDom: Raw<fabric.Image>;
+      let ratio;
+      function main() {
+        const width = stream.getVideoTracks()[0].getSettings().width!;
+        const height = stream.getVideoTracks()[0].getSettings().height!;
+        ratio = handleScale({ width, height });
+        videoEl.width = width;
+        videoEl.height = height;
+        if (canvasDom) {
+          fabricCanvas.value?.remove(canvasDom);
+        }
+        canvasDom = markRaw(
+          new fabric.Image(videoEl, {
+            top: rect?.top || 0,
+            left: rect?.left || 0,
+            width,
+            height,
+          })
+        );
+        appStore.allTrack.forEach((item) => {
+          if (item.id === id) {
+            if (item.canvasDom) {
+              item.canvasDom = canvasDom;
+            }
+          }
+        });
+        console.log(
+          '初始化',
+          ratio,
+          canvasDom.width,
+          canvasDom.height,
+          width * ratio,
+          height * ratio,
+          canvasDom
+        );
+        handleMoving({ canvasDom, id });
+        handleScaling({ canvasDom, id });
+        canvasDom.scale(ratio / window.devicePixelRatio);
+        fabricCanvas.value!.add(canvasDom);
+        resolve({ canvasDom, scale: ratio, videoEl });
+      }
+      main();
+      videoEl.addEventListener('resize', () => {
+        main();
+      });
     };
   });
 }
@@ -1425,6 +1470,9 @@ async function handleCache() {
         };
       });
     }
+    if ([MediaTypeEnum.metting, MediaTypeEnum.pk].includes(obj.type)) {
+      err.push(obj.id);
+    }
 
     if (item.type === MediaTypeEnum.media && item.video === 1) {
       queue.push(handleMediaVideo());
@@ -1499,6 +1547,7 @@ async function handleCache() {
     res.push(obj);
   });
   await Promise.all(queue);
+
   canvasVideoStream.value = pushCanvasRef.value!.captureStream();
   appStore.setAllTrack(res.filter((v) => !err.includes(v.id)));
 }
@@ -1639,12 +1688,13 @@ async function addMediaOk(val: AppRootState['allTrack'][0]) {
     cacheStore.setResourceList(res);
     console.log('获取摄像头成功');
   } else if (val.type === MediaTypeEnum.pk) {
-    const event = await handleUserMedia({
-      video: {
-        deviceId: val.deviceId,
-      },
-      audio: false,
-    });
+    // const event = await handleUserMedia({
+    //   video: {
+    //     deviceId: val.deviceId,
+    //   },
+    //   audio: false,
+    // });
+    const event = val.stream;
     if (!event) return;
     const videoTrack: AppRootState['allTrack'][0] = {
       id: getRandomEnglishString(6),
@@ -1675,6 +1725,38 @@ async function addMediaOk(val: AppRootState['allTrack'][0]) {
     appStore.setAllTrack(res);
     cacheStore.setResourceList(res);
     console.log('获取pk成功');
+  } else if (val.type === MediaTypeEnum.metting) {
+    const event = val.stream;
+    if (!event) return;
+    const videoTrack: AppRootState['allTrack'][0] = {
+      id: getRandomEnglishString(6),
+      openEye: true,
+      deviceId: val.deviceId,
+      audio: 2,
+      video: 1,
+      mediaName: val.mediaName,
+      type: MediaTypeEnum.metting,
+      track: event.getVideoTracks()[0],
+      trackid: event.getVideoTracks()[0].id,
+      stream: event,
+      streamid: event.id,
+      hidden: false,
+      muted: false,
+      scaleInfo: {},
+    };
+    const { canvasDom, videoEl, scale } = await autoCreateVideo({
+      stream: event,
+      id: videoTrack.id,
+    });
+    setScaleInfo({ canvasDom, track: videoTrack, scale });
+    videoTrack.videoEl = videoEl;
+    // @ts-ignore
+    videoTrack.canvasDom = canvasDom;
+
+    const res = [...appStore.allTrack, videoTrack];
+    appStore.setAllTrack(res);
+    cacheStore.setResourceList(res);
+    console.log('获取会议成功');
   } else if (val.type === MediaTypeEnum.microphone) {
     const event = await handleUserMedia({
       video: false,
@@ -2249,7 +2331,6 @@ function handleStartMedia(item: { type: MediaTypeEnum; txt: string }) {
           justify-content: space-between;
           margin: 5px 0;
           font-size: 14px;
-          height: 20px;
           cursor: pointer;
           user-select: none;
           .control {