shuisheng 2 lat temu
rodzic
commit
7030f9c183

+ 101 - 56
src/hooks/use-pull.ts

@@ -22,16 +22,16 @@ export function usePull({
   liveType: liveTypeEnum;
 }) {
   const route = useRoute();
-  const appStore = useAppStore();
   const userStore = useUserStore();
   const networkStore = useNetworkStore();
+  const appStore = useAppStore();
   const roomId = ref(route.params.roomId as string);
   const roomLiveType = ref<liveTypeEnum>(liveType);
-  const flvurl = ref('');
-  const hlsurl = ref('');
   const danmuStr = ref('');
   const autoplayVal = ref(false);
   const videoLoading = ref(false);
+  const flvurl = ref('');
+  const hlsurl = ref('');
   const sidebarList = ref<
     {
       socketId: string;
@@ -42,6 +42,7 @@ export function usePull({
   const {
     getSocketId,
     initWs,
+    roomLiveing,
     liveRoomInfo,
     roomNoLive,
     heartbeatTimer,
@@ -61,38 +62,103 @@ export function usePull({
   const { flvVideoEl, startFlvPlay } = useFlvPlay();
   const { hlsVideoEl, startHlsPlay } = useHlsPlay();
 
+  async function handleHlsPlay() {
+    console.log('handleHlsPlay');
+    videoLoading.value = true;
+    const { width, height } = await startHlsPlay({
+      hlsurl: hlsurl.value,
+    });
+    videoToCanvas({
+      videoEl: hlsVideoEl.value!,
+      targetEl: canvasRef.value!,
+      width,
+      height,
+    });
+    videoLoading.value = false;
+  }
+
+  async function handlePlay() {
+    if (roomLiveType.value === liveTypeEnum.srsFlvPull) {
+      console.log('srsFlvPull', autoplayVal.value);
+      if (!autoplayVal.value) return;
+      const { width, height } = await startFlvPlay({
+        flvurl: flvurl.value,
+      });
+      videoToCanvas({
+        videoEl: flvVideoEl.value!,
+        targetEl: canvasRef.value!,
+        width,
+        height,
+      });
+      videoLoading.value = false;
+    } else if (roomLiveType.value === liveTypeEnum.srsHlsPull) {
+      console.log('srsHlsPull', autoplayVal.value);
+      if (!autoplayVal.value) return;
+      handleHlsPlay();
+    }
+  }
+
+  watch(
+    () => autoplayVal.value,
+    (val) => {
+      console.log('autoplayVal变了', val);
+      if (val && roomLiveType.value === liveTypeEnum.webrtcPull) {
+        handlePlay();
+      }
+    }
+  );
+
+  watch(
+    () => roomLiveing.value,
+    (val) => {
+      if (val) {
+        flvurl.value = val.live?.live_room?.flv_url!;
+        hlsurl.value = val.live?.live_room?.hls_url!;
+        if (val && roomLiveType.value === liveTypeEnum.webrtcPull) {
+          handlePlay();
+        }
+      }
+    }
+  );
+  watch(
+    () => appStore.muted,
+    (newVal) => {
+      console.log('muted变了', newVal);
+      videoElArr.value.forEach((el) => {
+        el.muted = newVal;
+      });
+    }
+  );
+
   watch(
     () => localStream,
-    async (stream) => {
+    (stream) => {
       if (stream.value) {
         console.log('localStream变了');
         console.log('音频轨:', stream.value?.getAudioTracks());
         console.log('视频轨:', stream.value?.getVideoTracks());
-        if (roomLiveType.value === liveTypeEnum.srsFlvPull) {
-          if (!autoplayVal.value) return;
-          const { width, height } = await startFlvPlay({
-            flvurl: flvurl.value,
-          });
-          videoToCanvas({
-            videoEl: flvVideoEl.value!,
-            targetEl: canvasRef.value!,
-            width,
-            height,
+        if (roomLiveType.value === liveTypeEnum.webrtcPull) {
+          videoElArr.value.forEach((dom) => {
+            dom.remove();
           });
-          videoLoading.value = false;
-        } else if (roomLiveType.value === liveTypeEnum.srsHlsPull) {
-          if (!autoplayVal.value) return;
-          const { width, height } = await startHlsPlay({
-            hlsurl: hlsurl.value,
+          stream.value?.getVideoTracks().forEach((track) => {
+            console.log('视频轨enabled:', track.id, track.enabled);
+            const video = createVideo({});
+            video.id = track.id;
+            video.srcObject = new MediaStream([track]);
+            canvasRef.value?.appendChild(video);
+            videoElArr.value.push(video);
           });
-          videoToCanvas({
-            videoEl: hlsVideoEl.value!,
-            targetEl: canvasRef.value!,
-            width,
-            height,
+          stream.value?.getAudioTracks().forEach((track) => {
+            console.log('音频轨enabled:', track.id, track.enabled);
+            const video = createVideo({});
+            video.id = track.id;
+            video.srcObject = new MediaStream([track]);
+            canvasRef.value?.appendChild(video);
+            videoElArr.value.push(video);
           });
           videoLoading.value = false;
-        } else if (roomLiveType.value === liveTypeEnum.webrtcPull) {
+        } else if (roomLiveType.value === liveTypeEnum.srsWebrtcPull) {
           videoElArr.value.forEach((dom) => {
             dom.remove();
           });
@@ -112,14 +178,7 @@ export function usePull({
             canvasRef.value?.appendChild(video);
             videoElArr.value.push(video);
           });
-          // videoEl.srcObject = stream.value;
-          // canvasRef.value?.childNodes?.forEach((item) => {
-          //   item.remove();
-          // });
-          // canvasRef.value?.appendChild(videoEl);
           videoLoading.value = false;
-        } else if (roomLiveType.value === liveTypeEnum.srsWebrtcPull) {
-          console.log('lllll');
         }
       } else {
         videoElArr.value?.forEach((item) => {
@@ -139,13 +198,6 @@ export function usePull({
       if (userInfo && connected) {
         const instance = networkStore.wsMap.get(roomId.value);
         if (!instance) return;
-        // const data: IUpdateJoinInfo['data'] = {
-        //   live_room_id: Number(roomId.value),
-        // };
-        // instance.send({
-        //   msgType: WsMsgTypeEnum.updateJoinInfo,
-        //   data,
-        // });
       }
     }
   );
@@ -155,7 +207,12 @@ export function usePull({
     if (autoplayVal.value) {
       videoLoading.value = true;
     }
-    initWs({ roomId: roomId.value, isSRS, isAnchor: false });
+    initWs({
+      roomId: roomId.value,
+      isSRS,
+      isAnchor: false,
+      isPull: true,
+    });
   }
 
   function closeWs() {
@@ -172,26 +229,11 @@ export function usePull({
   function addVideo() {
     sidebarList.value.push({ socketId: getSocketId() });
     nextTick(() => {
-      liveUserList.value.forEach(async (item) => {
+      liveUserList.value.forEach((item) => {
         const socketId = item.id;
-        console.log(item, 333);
         if (socketId === getSocketId()) {
           localVideoRef.value[getSocketId()].srcObject = localStream.value;
         }
-        // if (!offerSended.value.has(socketId)) {
-        //   hooksRtcMap.value.add(
-        //     await startNewWebRtc({
-        //       receiver: socketId,
-        //       videoEl: localVideoRef.value[socketId],
-        //     })
-        //   );
-        //   console.log('执行sendOffer', {
-        //     sender: getSocketId(),
-        //     receiver: socketId,
-        //   });
-        //   sendOffer({ sender: getSocketId(), receiver: socketId });
-        //   offerSended.value.add(socketId);
-        // }
       });
     });
   }
@@ -238,6 +280,9 @@ export function usePull({
     keydownDanmu,
     sendDanmu,
     addVideo,
+    handleHlsPlay,
+    roomLiveType,
+    roomLiveing,
     autoplayVal,
     videoLoading,
     roomNoLive,

+ 0 - 694
src/hooks/use-pull22.ts

@@ -1,694 +0,0 @@
-import { getRandomString, judgeDevice } from 'billd-utils';
-import { Ref, nextTick, onUnmounted, reactive, ref, watch } from 'vue';
-import { useRoute } from 'vue-router';
-
-import { fetchRtcV1Play } from '@/api/srs';
-import { WEBSOCKET_URL } from '@/constant';
-import { useFlvPlay, useHlsPlay } from '@/hooks/use-play';
-import {
-  DanmuMsgTypeEnum,
-  IAnswer,
-  ICandidate,
-  IDanmu,
-  IJoin,
-  ILive,
-  ILiveUser,
-  IMessage,
-  IOffer,
-  IOtherJoin,
-  LiveRoomTypeEnum,
-  liveTypeEnum,
-} from '@/interface';
-import { WebRTCClass, audioElArr } from '@/network/webRTC';
-import {
-  WebSocketClass,
-  WsConnectStatusEnum,
-  WsMsgTypeEnum,
-  prettierReceiveWebsocket,
-} from '@/network/webSocket';
-import { useAppStore } from '@/store/app';
-import { useNetworkStore } from '@/store/network';
-import { useUserStore } from '@/store/user';
-import { createVideo, videoToCanvas } from '@/utils';
-
-export function usePull({
-  localVideoRef,
-  canvasRef,
-  isSRS,
-  liveType,
-}: {
-  localVideoRef: Ref<HTMLVideoElement[]>;
-  canvasRef: Ref<Element | undefined>;
-  isSRS?: boolean;
-  liveType: liveTypeEnum;
-}) {
-  const route = useRoute();
-  const appStore = useAppStore();
-  const userStore = useUserStore();
-  const networkStore = useNetworkStore();
-  const videoEl = createVideo({
-    muted: true,
-    autoplay: true,
-  });
-  const remoteVideoRef = ref(videoEl);
-  const heartbeatTimer = ref();
-  const roomId = ref(route.params.roomId as string);
-  const roomLiveType = ref<liveTypeEnum>(liveType);
-  const roomName = ref('');
-  const roomSocketId = ref('');
-  const userName = ref('');
-  const userAvatar = ref('');
-  const streamurl = ref('');
-  const flvurl = ref('');
-  const hlsurl = ref('');
-  const coverImg = ref('');
-  const danmuStr = ref('');
-  const balance = ref('0.00');
-  const currentLiveRoom = ref<ILive>();
-  const damuList = ref<IDanmu[]>([]);
-  const liveUserList = ref<ILiveUser[]>([]);
-  const autoplayVal = ref(false);
-  const videoLoading = ref(false);
-  const isDone = ref(false);
-  const roomNoLive = ref(false);
-  const localStream = ref();
-  const sidebarList = ref<
-    {
-      socketId: string;
-    }[]
-  >([]);
-
-  const track = reactive({
-    audio: 1,
-    video: 1,
-  });
-
-  const giftList = ref([
-    { name: '鲜花', ico: '', price: '免费' },
-    { name: '肥宅水', ico: '', price: '2元' },
-    { name: '小鸡腿', ico: '', price: '3元' },
-    { name: '大鸡腿', ico: '', price: '5元' },
-    { name: '一杯咖啡', ico: '', price: '10元' },
-  ]);
-  const offerSended = ref(new Set());
-  const hooksRtcMap = ref(new Set());
-  const sender = ref();
-
-  const { flvVideoEl, startFlvPlay } = useFlvPlay();
-  const { hlsVideoEl, startHlsPlay } = useHlsPlay();
-
-  onUnmounted(() => {
-    clearInterval(heartbeatTimer.value);
-  });
-
-  watch(
-    () => appStore.allTrack,
-    () => {
-      // networkStore.rtcMap.forEach((rtc) => {
-      //   if (appStore.getTrackInfo().audio > 0) {
-      //     rtc!.peerConnection?.addTransceiver('audio', {
-      //       direction: 'recvonly',
-      //     });
-      //   }
-      //   if (appStore.getTrackInfo().video > 0) {
-      //     rtc!.peerConnection?.addTransceiver('video', {
-      //       direction: 'recvonly',
-      //     });
-      //   }
-      // });
-    },
-    { deep: true }
-  );
-
-  watch(
-    () => appStore.muted,
-    (val) => {
-      remoteVideoRef.value.muted = val;
-      audioElArr.forEach((el) => {
-        console.log(el, el.muted);
-        el.muted = val;
-      });
-    }
-  );
-
-  watch(
-    [
-      () => userStore.userInfo,
-      () => networkStore.wsMap.get(roomId.value)?.socketIo?.connected,
-    ],
-    ([userInfo, connected]) => {
-      if (userInfo) {
-        balance.value = userInfo.wallet?.balance || '0.00';
-      }
-      if (userInfo && connected) {
-        const instance = networkStore.wsMap.get(roomId.value);
-        if (!instance) return;
-        // const data: IUpdateJoinInfo['data'] = {
-        //   live_room_id: Number(roomId.value),
-        // };
-        // instance.send({
-        //   msgType: WsMsgTypeEnum.updateJoinInfo,
-        //   data,
-        // });
-      }
-    }
-  );
-
-  function initPull(autolay = true) {
-    autoplayVal.value = autolay;
-    if (autoplayVal.value) {
-      videoLoading.value = true;
-    }
-    console.warn('开始new WebSocketClass');
-    const ws = new WebSocketClass({
-      roomId: roomId.value,
-      url: WEBSOCKET_URL,
-      isAnchor: false,
-    });
-    ws.update();
-    initWsReceive();
-
-    remoteVideoRef.value?.addEventListener('loadstart', () => {
-      console.warn('视频流-loadstart');
-      const rtc = networkStore.getRtcMap(roomId.value);
-      if (!rtc) return;
-      rtc.update();
-    });
-
-    remoteVideoRef.value?.addEventListener('loadedmetadata', () => {
-      console.warn('视频流-loadedmetadata');
-      if (
-        roomLiveType.value === liveTypeEnum.webrtcPull ||
-        roomLiveType.value === liveTypeEnum.srsWebrtcPull
-      ) {
-        canvasRef.value?.appendChild(remoteVideoRef.value);
-      }
-      videoLoading.value = false;
-      const rtc = networkStore.getRtcMap(roomId.value);
-      if (!rtc) return;
-      rtc.update();
-    });
-  }
-
-  function handleHeartbeat() {
-    heartbeatTimer.value = setInterval(() => {
-      const instance = networkStore.wsMap.get(roomId.value);
-      if (!instance) return;
-      instance.send({
-        msgType: WsMsgTypeEnum.heartbeat,
-      });
-    }, 1000 * 5);
-  }
-
-  function closeWs() {
-    const instance = networkStore.wsMap.get(roomId.value);
-    instance?.close();
-  }
-
-  function closeRtc() {
-    networkStore.rtcMap.forEach((rtc) => {
-      rtc.close();
-    });
-  }
-
-  function getSocketId() {
-    return networkStore.wsMap.get(roomId.value!)?.socketIo?.id || '-1';
-  }
-
-  function sendJoin() {
-    const instance = networkStore.wsMap.get(roomId.value);
-    if (!instance) return;
-    const joinData: IJoin['data'] = {
-      live_room: {
-        id: Number(roomId.value),
-        name: roomName.value,
-        type: isSRS ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc,
-      },
-      track,
-    };
-    instance.send({
-      msgType: WsMsgTypeEnum.join,
-      data: joinData,
-    });
-  }
-
-  async function sendOffer({
-    sender,
-    receiver,
-  }: {
-    sender: string;
-    receiver: string;
-  }) {
-    console.log(isDone.value);
-    if (isDone.value) return;
-    const instance = networkStore.wsMap.get(roomId.value);
-    console.log(instance, roomId.value);
-    if (!instance) return;
-    const rtc = networkStore.getRtcMap(`${roomId.value}___${receiver}`);
-    if (!rtc) return;
-    const sdp = await rtc.createOffer();
-    await rtc.setLocalDescription(sdp!);
-    const offerData = {
-      sdp,
-      sender,
-      receiver,
-      live_room_id: roomId.value,
-    };
-    instance.send({
-      msgType: WsMsgTypeEnum.offer,
-      data: offerData,
-    });
-  }
-
-  function addVideo() {
-    sidebarList.value.push({ socketId: getSocketId() });
-    nextTick(() => {
-      liveUserList.value.forEach(async (item) => {
-        const socketId = item.id;
-        console.log(item, 333);
-        if (socketId === getSocketId()) {
-          localVideoRef.value[getSocketId()].srcObject = localStream.value;
-        }
-        if (!offerSended.value.has(socketId)) {
-          hooksRtcMap.value.add(
-            await startNewWebRtc({
-              receiver: socketId,
-              videoEl: localVideoRef.value[socketId],
-            })
-          );
-          console.log('执行sendOffer', {
-            sender: getSocketId(),
-            receiver: socketId,
-          });
-          sendOffer({ sender: getSocketId(), receiver: socketId });
-          offerSended.value.add(socketId);
-        }
-      });
-    });
-  }
-
-  /** 原生的webrtc时,receiver必传 */
-  async function startNewWebRtc({
-    receiver,
-    videoEl = remoteVideoRef.value!,
-  }: {
-    receiver: string;
-    videoEl?: HTMLVideoElement;
-  }) {
-    let rtc: WebRTCClass;
-    if (isSRS) {
-      if (!autoplayVal.value) return;
-      console.warn('开始new SRSWebRTCClass', getSocketId());
-      rtc = new WebRTCClass({
-        roomId: `${roomId.value}___${getSocketId()}`,
-        videoEl,
-        isSRS: true,
-        direction: 'recvonly',
-        receiver,
-      });
-      rtc.update();
-      try {
-        const offer = await rtc.createOffer();
-        if (!offer) return;
-        await rtc.setLocalDescription(offer);
-        const res = await fetchRtcV1Play({
-          api: `/rtc/v1/play/`,
-          clientip: null,
-          sdp: offer.sdp!,
-          streamurl: streamurl.value,
-          tid: getRandomString(10),
-        });
-        await rtc.setRemoteDescription(
-          new RTCSessionDescription({ type: 'answer', sdp: res.data.sdp })
-        );
-      } catch (error) {
-        console.log(error);
-      }
-    } else {
-      if (!autoplayVal.value) return;
-      console.warn('开始new WebRTCClass');
-      rtc = new WebRTCClass({
-        roomId: `${roomId.value}___${receiver!}`,
-        videoEl,
-        isSRS: false,
-        direction: 'recvonly',
-        receiver,
-      });
-    }
-    return rtc;
-  }
-
-  function keydownDanmu(event: KeyboardEvent) {
-    const key = event.key.toLowerCase();
-    if (key === 'enter') {
-      event.preventDefault();
-      sendDanmu();
-    }
-  }
-
-  function sendDanmu() {
-    if (!danmuStr.value.trim().length) {
-      window.$message.warning('请输入弹幕内容!');
-      return;
-    }
-    const instance = networkStore.wsMap.get(roomId.value);
-    if (!instance) return;
-    const danmu: IDanmu = {
-      socket_id: getSocketId(),
-      userInfo: userStore.userInfo,
-      msgType: DanmuMsgTypeEnum.danmu,
-      msg: danmuStr.value,
-    };
-    const messageData: IMessage['data'] = {
-      msg: danmuStr.value,
-      msgType: DanmuMsgTypeEnum.danmu,
-      live_room_id: Number(roomId.value),
-    };
-    instance.send({
-      msgType: WsMsgTypeEnum.message,
-      data: messageData,
-    });
-    damuList.value.push(danmu);
-    danmuStr.value = '';
-  }
-
-  function initWsReceive() {
-    const instance = networkStore.wsMap.get(roomId.value);
-    if (!instance?.socketIo) return;
-    // websocket连接成功
-    instance.socketIo.on(WsConnectStatusEnum.connect, () => {
-      prettierReceiveWebsocket(WsConnectStatusEnum.connect);
-      handleHeartbeat();
-      if (!instance) return;
-      instance.status = WsConnectStatusEnum.connect;
-      instance.update();
-      sendJoin();
-    });
-
-    // websocket连接断开
-    instance.socketIo.on(WsConnectStatusEnum.disconnect, () => {
-      prettierReceiveWebsocket(WsConnectStatusEnum.disconnect);
-      if (!instance) return;
-      instance.status = WsConnectStatusEnum.disconnect;
-      instance.update();
-    });
-
-    // 用户加入房间
-    instance.socketIo.on(
-      WsMsgTypeEnum.joined,
-      async (data: { data: ILive }) => {
-        prettierReceiveWebsocket(WsMsgTypeEnum.joined, data);
-        roomSocketId.value = data.data.socket_id!;
-        roomName.value = data.data.live_room?.name!;
-        userName.value = data.data.user?.username!;
-        userAvatar.value = data.data.user?.avatar!;
-        track.audio = data.data.track_audio!;
-        track.video = data.data.track_video!;
-        coverImg.value = data.data.live_room?.cover_img!;
-        flvurl.value = data.data.live_room?.flv_url!;
-        hlsurl.value = data.data.live_room?.hls_url!;
-        streamurl.value = data.data.live_room!.rtmp_url!.replace(
-          'rtmp',
-          'webrtc'
-        );
-        currentLiveRoom.value = data.data;
-        if (roomLiveType.value === liveTypeEnum.srsWebrtcPull) {
-          instance.send({ msgType: WsMsgTypeEnum.getLiveUser });
-        } else if (roomLiveType.value === liveTypeEnum.srsFlvPull) {
-          if (!autoplayVal.value) return;
-          const { width, height } = await startFlvPlay({
-            flvurl: flvurl.value,
-          });
-          videoToCanvas({
-            videoEl: flvVideoEl.value!,
-            targetEl: canvasRef.value!,
-            width,
-            height,
-            // width: flvPlayer.value?.mediaInfo.width!,
-            // height: flvPlayer.value?.mediaInfo.height!,
-          });
-          videoLoading.value = false;
-        } else if (roomLiveType.value === liveTypeEnum.srsHlsPull) {
-          if (!autoplayVal.value) return;
-          const { width, height } = await startHlsPlay({
-            hlsurl: hlsurl.value,
-          });
-          videoToCanvas({
-            videoEl: hlsVideoEl.value!,
-            targetEl: canvasRef.value!,
-            width,
-            height,
-          });
-          videoLoading.value = false;
-        } else if (
-          data.data.live_room?.type === LiveRoomTypeEnum.user_obs ||
-          data.data.live_room?.type === LiveRoomTypeEnum.system
-        ) {
-          if (!autoplayVal.value) return;
-          if (judgeDevice().isIphone) {
-            const { width, height } = await startHlsPlay({
-              hlsurl: flvurl.value,
-            });
-            videoToCanvas({
-              videoEl: hlsVideoEl.value!,
-              targetEl: canvasRef.value!,
-              width,
-              height,
-            });
-          } else {
-            const { width, height } = await startFlvPlay({
-              flvurl: flvurl.value,
-            });
-            videoToCanvas({
-              videoEl: flvVideoEl.value!,
-              targetEl: canvasRef.value!,
-              width,
-              height,
-            });
-          }
-          videoLoading.value = false;
-        }
-        instance.send({
-          msgType: WsMsgTypeEnum.getLiveUser,
-        });
-      }
-    );
-
-    // 收到offer
-    instance.socketIo.on(WsMsgTypeEnum.offer, async (data: IOffer) => {
-      prettierReceiveWebsocket(
-        WsMsgTypeEnum.offer,
-        `发送者:${data.data.sender},接收者:${data.data.receiver}`,
-        data
-      );
-      if (isSRS) return;
-      if (!instance) return;
-      if (data.data.receiver === getSocketId()) {
-        if (!data.is_anchor) {
-          sidebarList.value.push({ socketId: data.data.sender });
-        }
-        await nextTick(async () => {
-          console.log('收到offer,这个offer是发给我的', data);
-          sender.value = data.data.sender;
-          let rtc = networkStore.getRtcMap(
-            `${roomId.value}___${data.data.sender}`
-          );
-          if (!rtc) {
-            rtc = await startNewWebRtc({
-              receiver: data.data.sender,
-              videoEl: data.is_anchor
-                ? remoteVideoRef.value
-                : localVideoRef.value[data.data.sender],
-            });
-          }
-          // const rtc = await startNewWebRtc({
-          //   receiver: data.data.sender,
-          //   videoEl: data.is_anchor
-          //     ? remoteVideoRef.value
-          //     : localVideoRef.value[data.data.sender],
-          // });
-          if (rtc) {
-            await rtc.setRemoteDescription(data.data.sdp);
-            const sdp = await rtc.createAnswer();
-            await rtc.setLocalDescription(sdp!);
-            const answerData: IAnswer = {
-              sdp,
-              sender: getSocketId(),
-              receiver: data.data.sender,
-              live_room_id: data.data.live_room_id,
-            };
-            instance.send({
-              msgType: WsMsgTypeEnum.answer,
-              data: answerData,
-            });
-          }
-        });
-      } else {
-        console.log('收到offer,但是这个offer不是发给我的');
-      }
-    });
-
-    // 收到answer
-    instance.socketIo.on(WsMsgTypeEnum.answer, async (data: IOffer) => {
-      prettierReceiveWebsocket(
-        WsMsgTypeEnum.answer,
-        `发送者:${data.data.sender},接收者:${data.data.receiver}`,
-        data
-      );
-      if (isSRS) return;
-      if (!instance) return;
-      const rtc = networkStore.getRtcMap(`${roomId.value}___${data.socket_id}`);
-      if (!rtc) return;
-      rtc.update();
-      if (data.data.receiver === getSocketId()) {
-        console.log('收到answer,这个answer是发给我的');
-        await rtc.setRemoteDescription(data.data.sdp);
-      } else {
-        console.log('收到answer,但这个answer不是发给我的');
-      }
-    });
-
-    // 收到candidate
-    instance.socketIo.on(WsMsgTypeEnum.candidate, (data: ICandidate) => {
-      prettierReceiveWebsocket(
-        WsMsgTypeEnum.candidate,
-        `发送者:${data.data.sender},接收者:${data.data.receiver}`,
-        data
-      );
-      if (isSRS) return;
-      if (!instance) return;
-      const rtc = networkStore.getRtcMap(`${roomId.value}___${data.socket_id}`);
-      if (!rtc) return;
-      if (data.data.receiver === getSocketId()) {
-        console.log('是发给我的candidate');
-        const candidate = new RTCIceCandidate({
-          sdpMid: data.data.sdpMid,
-          sdpMLineIndex: data.data.sdpMLineIndex,
-          candidate: data.data.candidate,
-        });
-        rtc.peerConnection
-          ?.addIceCandidate(candidate)
-          .then(() => {
-            console.log('candidate成功');
-          })
-          .catch((err) => {
-            console.error('candidate失败', err);
-          });
-      } else {
-        console.log('不是发给我的candidate');
-      }
-    });
-
-    // 管理员正在直播
-    instance.socketIo.on(WsMsgTypeEnum.roomLiveing, (data) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.roomLiveing, data);
-      if (isSRS && roomLiveType.value !== liveTypeEnum.srsFlvPull) {
-        startNewWebRtc({ receiver: getSocketId() });
-      }
-    });
-
-    // 管理员不在直播
-    instance.socketIo.on(WsMsgTypeEnum.roomNoLive, (data) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.roomNoLive, data);
-      roomNoLive.value = true;
-      closeRtc();
-    });
-
-    // 当前所有在线用户
-    instance.socketIo.on(WsMsgTypeEnum.liveUser, (data: ILiveUser[]) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.liveUser, data);
-      if (!instance) return;
-      liveUserList.value = data;
-      // batchSendOffer();
-    });
-
-    // 收到用户发送消息
-    instance.socketIo.on(WsMsgTypeEnum.message, (data: IMessage) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.message, data);
-      if (!instance) return;
-      const danmu: IDanmu = {
-        msgType: DanmuMsgTypeEnum.danmu,
-        socket_id: data.socket_id,
-        userInfo: data.user_info,
-        msg: data.data.msg,
-      };
-      damuList.value.push(danmu);
-    });
-
-    // 其他用户加入房间
-    instance.socketIo.on(WsMsgTypeEnum.otherJoin, (data: IOtherJoin) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.otherJoin, data);
-      const danmu: IDanmu = {
-        msgType: DanmuMsgTypeEnum.otherJoin,
-        socket_id: data.data.join_socket_id,
-        userInfo: data.data.liveRoom.user,
-        msg: '',
-      };
-      damuList.value.push(danmu);
-      liveUserList.value.push({
-        id: data.data.join_socket_id,
-        userInfo: data.data.liveRoom.user,
-      });
-    });
-
-    // 用户离开房间
-    instance.socketIo.on(WsMsgTypeEnum.leave, (data) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.leave, data);
-      if (!instance) return;
-      instance.send({
-        msgType: WsMsgTypeEnum.leave,
-        data: { roomId: instance.roomId },
-      });
-    });
-
-    // 用户离开房间完成
-    instance.socketIo.on(WsMsgTypeEnum.leaved, (data) => {
-      prettierReceiveWebsocket(WsMsgTypeEnum.leaved, data);
-      networkStore.rtcMap
-        .get(`${roomId.value}___${data.socketId as string}`)
-        ?.close();
-      networkStore.removeRtc(`${roomId.value}___${data.socketId as string}`);
-      if (!instance) return;
-      const res = liveUserList.value.filter(
-        (item) => item.id !== data.socketId
-      );
-      liveUserList.value = res;
-      const danmu: IDanmu = {
-        msgType: DanmuMsgTypeEnum.userLeaved,
-        socket_id: data.socketId,
-        userInfo: data.data.userInfo,
-        msg: '',
-      };
-      damuList.value.push(danmu);
-    });
-  }
-
-  return {
-    initPull,
-    closeWs,
-    closeRtc,
-    getSocketId,
-    keydownDanmu,
-    sendDanmu,
-    addVideo,
-    autoplayVal,
-    videoLoading,
-    balance,
-    roomLiveType,
-    roomSocketId,
-    roomName,
-    userName,
-    userAvatar,
-    currentLiveRoom,
-    hlsurl,
-    coverImg,
-    roomNoLive,
-    damuList,
-    giftList,
-    liveUserList,
-    danmuStr,
-    localStream,
-    sender,
-    sidebarList,
-  };
-}

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

@@ -185,6 +185,7 @@ export function usePush({
       isAnchor: true,
       roomId: roomId.value,
       isSRS,
+      isPull: false,
       currentMaxBitrate: currentMaxBitrate.value,
       currentMaxFramerate: currentMaxFramerate.value,
       currentResolutionRatio: currentResolutionRatio.value,

+ 145 - 102
src/hooks/use-ws.ts

@@ -1,7 +1,7 @@
 import { getRandomString } from 'billd-utils';
-import { ref, watch } from 'vue';
+import { reactive, ref, watch } from 'vue';
 
-import { fetchRtcV1Publish } from '@/api/srs';
+import { fetchRtcV1Play, fetchRtcV1Publish } from '@/api/srs';
 import { WEBSOCKET_URL } from '@/constant';
 import {
   DanmuMsgTypeEnum,
@@ -38,10 +38,13 @@ export const useWs = () => {
   const roomId = ref('');
   const roomName = ref('');
   const roomNoLive = ref(false);
+  const roomLiveing = ref<IJoin['data']>();
   const liveRoomInfo = ref<ILive>();
   const isAnchor = ref(false);
   const joined = ref(false);
   const isSRS = ref(false);
+  const isPull = ref(false);
+  const trackInfo = reactive({ track_audio: 1, track_video: 1 });
   const localVideo = ref<HTMLVideoElement>(document.createElement('video'));
   const localStream = ref<MediaStream>();
   const maxBitrate = ref([
@@ -132,13 +135,6 @@ export const useWs = () => {
 
   const damuList = ref<IDanmu[]>([]);
 
-  watch(
-    () => appStore.muted,
-    (newVal) => {
-      console.log(newVal);
-    }
-  );
-
   watch(
     () => appStore.allTrack,
     (newTrack, oldTrack) => {
@@ -156,13 +152,15 @@ export const useWs = () => {
       console.log('旧的allTrack视频轨', localStream.value?.getVideoTracks());
       localStream.value = mixedStream;
       if (isSRS.value) {
-        networkStore.rtcMap.forEach((rtc) => {
-          rtc.close();
-        });
-        startNewWebRtc({
-          receiver: 'srs',
-          videoEl: localVideo.value,
-        });
+        if (!isPull.value) {
+          networkStore.rtcMap.forEach((rtc) => {
+            rtc.close();
+          });
+          startNewWebRtc({
+            receiver: 'srs',
+            videoEl: localVideo.value,
+          });
+        }
       }
     },
     { deep: true }
@@ -228,39 +226,39 @@ export const useWs = () => {
     console.log('addTrack后结果的音频轨', mixedStream.getAudioTracks());
     console.log('addTrack后结果的视频轨', mixedStream.getVideoTracks());
     localStream.value = mixedStream;
-    let resUrl = '';
-    const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url!;
-    if (rtmpUrl.indexOf('type=') === -1) {
-      resUrl += `${rtmpUrl}&type=${
-        isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-      }`;
-    } else {
-      resUrl = rtmpUrl.replace(
-        /type=([0-9]+)/,
-        `type=${
+    // srs不需要更新,因为更新了之后,跟着就关闭当前rtc然后重新new一个新的rtc了
+    if (!isSRS.value) {
+      let resUrl = '';
+      const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url!;
+      if (rtmpUrl.indexOf('type=') === -1) {
+        resUrl += `${rtmpUrl}&type=${
           isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-        }`
-      );
-    }
-    const data: IUpdateJoinInfo['data'] = {
-      live_room_id: Number(roomId.value),
-      track: {
-        audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
-        video: appStore.getTrackInfo().video > 0 ? 1 : 2,
-      },
-      rtmp_url: resUrl,
-    };
-    networkStore.wsMap.get(roomId.value)?.send({
-      msgType: WsMsgTypeEnum.updateJoinInfo,
-      data,
-    });
-    setTimeout(() => {
+        }`;
+      } else {
+        resUrl = rtmpUrl.replace(
+          /type=([0-9]+)/,
+          `type=${
+            isSRS.value
+              ? LiveRoomTypeEnum.user_srs
+              : LiveRoomTypeEnum.user_wertc
+          }`
+        );
+      }
+      const data: IUpdateJoinInfo['data'] = {
+        live_room_id: Number(roomId.value),
+        track: {
+          audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
+          video: appStore.getTrackInfo().video > 0 ? 1 : 2,
+        },
+        rtmp_url: resUrl,
+      };
       networkStore.wsMap.get(roomId.value)?.send({
         msgType: WsMsgTypeEnum.updateJoinInfo,
         data,
       });
-    }, 1000);
+    }
   }
+
   function delTrack(delTrackInfo: AppRootState['allTrack'][0]) {
     if (isAnchor.value) {
       networkStore.rtcMap.forEach((rtc) => {
@@ -270,7 +268,6 @@ export const useWs = () => {
         if (sender) {
           console.log('删除track', delTrackInfo, sender);
           rtc.peerConnection?.removeTrack(sender);
-          sender.replaceTrack(null);
         }
       });
     }
@@ -282,32 +279,36 @@ export const useWs = () => {
     console.log('delTrack后结果的音频轨', mixedStream.getAudioTracks());
     console.log('delTrack后结果的视频轨', mixedStream.getVideoTracks());
     localStream.value = mixedStream;
-    let resUrl = '';
-    const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url!;
-    if (rtmpUrl.indexOf('type=') === -1) {
-      resUrl += `${rtmpUrl}&type=${
-        isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-      }`;
-    } else {
-      resUrl = rtmpUrl.replace(
-        /type=([0-9]+)/,
-        `type=${
+    if (!isSRS.value) {
+      let resUrl = '';
+      const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url!;
+      if (rtmpUrl.indexOf('type=') === -1) {
+        resUrl += `${rtmpUrl}&type=${
           isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-        }`
-      );
+        }`;
+      } else {
+        resUrl = rtmpUrl.replace(
+          /type=([0-9]+)/,
+          `type=${
+            isSRS.value
+              ? LiveRoomTypeEnum.user_srs
+              : LiveRoomTypeEnum.user_wertc
+          }`
+        );
+      }
+      const data: IUpdateJoinInfo['data'] = {
+        live_room_id: Number(roomId.value),
+        track: {
+          audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
+          video: appStore.getTrackInfo().video > 0 ? 1 : 2,
+        },
+        rtmp_url: resUrl,
+      };
+      networkStore.wsMap.get(roomId.value)?.send({
+        msgType: WsMsgTypeEnum.updateJoinInfo,
+        data,
+      });
     }
-    const data: IUpdateJoinInfo['data'] = {
-      live_room_id: Number(roomId.value),
-      track: {
-        audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
-        video: appStore.getTrackInfo().video > 0 ? 1 : 2,
-      },
-      rtmp_url: resUrl,
-    };
-    networkStore.wsMap.get(roomId.value)?.send({
-      msgType: WsMsgTypeEnum.updateJoinInfo,
-      data,
-    });
   }
 
   function getSocketId() {
@@ -328,6 +329,7 @@ export const useWs = () => {
       });
     }, 1000 * 5);
   }
+
   async function sendOffer({
     sender,
     receiver,
@@ -355,16 +357,41 @@ export const useWs = () => {
     } else {
       const sdp = await rtc.createOffer();
       await rtc.setLocalDescription(sdp!);
-      const res = await fetchRtcV1Publish({
-        api: `/rtc/v1/publish/`,
-        clientip: null,
-        sdp: sdp!.sdp!,
-        streamurl: userStore.userInfo!.live_rooms![0]!.rtmp_url!.replace(
-          'rtmp',
-          'webrtc'
-        ),
-        tid: getRandomString(10),
-      });
+      let res;
+      if (isPull.value) {
+        res = await fetchRtcV1Play({
+          api: `/rtc/v1/play/`,
+          clientip: null,
+          sdp: sdp!.sdp!,
+          streamurl: userStore.userInfo!.live_rooms![0]!.rtmp_url!.replace(
+            'rtmp',
+            'webrtc'
+          ),
+          tid: getRandomString(10),
+        });
+      } else {
+        res = await fetchRtcV1Publish({
+          api: `/rtc/v1/publish/`,
+          clientip: null,
+          sdp: sdp!.sdp!,
+          streamurl: userStore.userInfo!.live_rooms![0]!.rtmp_url!.replace(
+            'rtmp',
+            'webrtc'
+          ),
+          tid: getRandomString(10),
+        });
+        const data: IUpdateJoinInfo['data'] = {
+          live_room_id: Number(roomId.value),
+          track: {
+            audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
+            video: appStore.getTrackInfo().video > 0 ? 1 : 2,
+          },
+        };
+        networkStore.wsMap.get(roomId.value)?.send({
+          msgType: WsMsgTypeEnum.updateJoinInfo,
+          data,
+        });
+      }
       if (res.data.code !== 0) {
         console.error('/rtc/v1/publish/拿不到sdp');
         return;
@@ -395,18 +422,23 @@ export const useWs = () => {
     const instance = networkStore.wsMap.get(roomId.value);
     if (!instance) return;
     let resUrl = '';
-    const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url!;
-    if (rtmpUrl.indexOf('type=') === -1) {
-      resUrl += `${rtmpUrl}&type=${
-        isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-      }`;
-    } else {
-      resUrl = rtmpUrl.replace(
-        /type=([0-9]+)/,
-        `type=${
+    const rtmpUrl = userStore.userInfo?.live_rooms?.[0].rtmp_url;
+    // 如果是用户看直播,发送join时不需要rtmpUrl;只有房主直播的时候需要带rtmpUrl
+    if (rtmpUrl) {
+      if (rtmpUrl.indexOf('type=') === -1) {
+        resUrl += `${rtmpUrl}&type=${
           isSRS.value ? LiveRoomTypeEnum.user_srs : LiveRoomTypeEnum.user_wertc
-        }`
-      );
+        }`;
+      } else {
+        resUrl = rtmpUrl.replace(
+          /type=([0-9]+)/,
+          `type=${
+            isSRS.value
+              ? LiveRoomTypeEnum.user_srs
+              : LiveRoomTypeEnum.user_wertc
+          }`
+        );
+      }
     }
     const joinData: IJoin['data'] = {
       live_room: {
@@ -418,9 +450,9 @@ export const useWs = () => {
           : LiveRoomTypeEnum.user_wertc,
         rtmp_url: resUrl,
       },
-      track: {
-        audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
-        video: appStore.getTrackInfo().video > 0 ? 1 : 2,
+      live: {
+        track_audio: appStore.getTrackInfo().audio > 0 ? 1 : 2,
+        track_video: appStore.getTrackInfo().video > 0 ? 1 : 2,
       },
     };
     instance.send({
@@ -461,15 +493,24 @@ export const useWs = () => {
         roomId: `${roomId.value}___${receiver!}`,
         videoEl,
         isSRS: true,
-        direction: 'sendonly',
         receiver,
       });
+      if (isPull.value) {
+        if (trackInfo.track_video === 1) {
+          rtc.peerConnection?.addTransceiver('video', {
+            direction: 'recvonly',
+          });
+        }
+        if (trackInfo.track_audio === 1) {
+          rtc.peerConnection?.addTransceiver('audio', {
+            direction: 'recvonly',
+          });
+        }
+      }
       // handleNegotiationneeded({
       //   roomId: `${roomId.value}___${receiver}`,
       //   isSRS: true,
       // });
-      rtc.peerConnection?.addTransceiver('audio', { direction: 'sendonly' });
-      // rtc.peerConnection?.addTransceiver('video', { direction: 'sendonly' });
       rtc.localStream = localStream.value;
       localStream.value?.getTracks().forEach((track) => {
         console.warn(
@@ -477,10 +518,6 @@ export const useWs = () => {
           track.id,
           localStream.value?.id
         );
-        // rtc.peerConnection?.addTransceiver(track, {
-        //   streams: [localStream.value!],
-        //   direction: 'sendonly',
-        // });
         rtc.peerConnection?.addTrack(track, localStream.value!);
       });
       sendOffer({
@@ -496,7 +533,6 @@ export const useWs = () => {
         roomId: `${roomId.value}___${receiver!}`,
         videoEl,
         isSRS: false,
-        direction: 'sendonly',
         receiver,
       });
       if (isAnchor.value) {
@@ -630,8 +666,10 @@ export const useWs = () => {
     });
 
     // 管理员正在直播
-    ws.socketIo.on(WsMsgTypeEnum.roomLiveing, (data) => {
+    ws.socketIo.on(WsMsgTypeEnum.roomLiveing, (data: IJoin) => {
       prettierReceiveWebsocket(WsMsgTypeEnum.roomLiveing, data);
+      console.log(data.data, 333323);
+      roomLiveing.value = data.data;
     });
 
     // 管理员不在直播
@@ -660,8 +698,10 @@ export const useWs = () => {
     // 用户加入房间完成
     ws.socketIo.on(WsMsgTypeEnum.joined, (data: IJoin) => {
       prettierReceiveWebsocket(WsMsgTypeEnum.joined, data);
-      handleHeartbeat(data.data.live_id || -1);
+      handleHeartbeat(data.data.live?.id || -1);
       joined.value = true;
+      trackInfo.track_audio = data.data.live?.track_audio!;
+      trackInfo.track_video = data.data.live?.track_video!;
       liveUserList.value.push({
         id: `${getSocketId()}`,
         userInfo: data.user_info,
@@ -735,6 +775,7 @@ export const useWs = () => {
     isAnchor: boolean;
     roomId: string;
     isSRS: boolean;
+    isPull: boolean;
     currentResolutionRatio?: number;
     currentMaxFramerate?: number;
     currentMaxBitrate?: number;
@@ -751,6 +792,7 @@ export const useWs = () => {
       currentResolutionRatio.value = data.currentResolutionRatio;
     }
     isSRS.value = data.isSRS;
+    isPull.value = data.isPull;
     new WebSocketClass({
       roomId: roomId.value,
       url: WEBSOCKET_URL,
@@ -764,6 +806,7 @@ export const useWs = () => {
     initWs,
     addTrack,
     delTrack,
+    roomLiveing,
     liveRoomInfo,
     roomNoLive,
     heartbeatTimer,

+ 3 - 3
src/interface.ts

@@ -338,7 +338,7 @@ export interface IUpdateJoinInfo {
   data: {
     live_room_id: number;
     track?: { audio: number; video: number };
-    rtmp_url: string;
+    rtmp_url?: string;
   };
 }
 
@@ -377,9 +377,9 @@ export interface IJoin {
   is_anchor: boolean;
   user_info?: IUser;
   data: {
-    live_id?: number;
+    live?: ILive;
     live_room: ILiveRoom;
-    track: { audio: number; video: number };
+    // track: { audio: number; video: number };
   };
 }
 

+ 1 - 0
src/layout/pc/head/index.vue

@@ -282,6 +282,7 @@ const resource = ref([
   },
   {
     label: 'billd-live-admin',
+    url: 'https://live-admin.hsslive.cn',
   },
 ]);
 const plugins = ref([

+ 0 - 5
src/network/webRTC.ts

@@ -15,8 +15,6 @@ export class WebRTCClass {
 
   videoEl: HTMLVideoElement;
 
-  direction: RTCRtpTransceiverDirection;
-
   peerConnection: RTCPeerConnection | null = null;
 
   /** 最大码率 */
@@ -50,12 +48,10 @@ export class WebRTCClass {
     maxFramerate?: number;
     resolutionRatio?: number;
     isSRS: boolean;
-    direction: RTCRtpTransceiverDirection;
     receiver: string;
   }) {
     this.roomId = data.roomId;
     this.videoEl = data.videoEl;
-    this.direction = data.direction;
     this.receiver = data.receiver;
     if (data.maxBitrate) {
       this.maxBitrate = data.maxBitrate;
@@ -161,7 +157,6 @@ export class WebRTCClass {
         });
       }
     });
-    console.log(addTrack.length, 'pppppo');
     if (addTrack.length) {
       appStore.setAllTrack([...appStore.allTrack, ...addTrack]);
     }

+ 22 - 2
src/router/index.ts

@@ -191,14 +191,34 @@ router.beforeEach((to, from, next) => {
   if (isMobile() && !isIPad()) {
     if (!Object.keys(mobileRouterName).includes(to.name as string)) {
       // 当前移动端,但是跳转了非移动端路由
-      return next({ name: mobileRouterName.h5 });
+      console.log('当前移动端,但是跳转了非移动端路由', to, from);
+      if (to.name === routerName.pull) {
+        return next({
+          name: mobileRouterName.h5Room,
+          params: { roomId: to.params.roomId },
+        });
+      } else {
+        return next({
+          name: mobileRouterName.h5,
+        });
+      }
     } else {
       return next();
     }
   } else {
     if (Object.keys(mobileRouterName).includes(to.name as string)) {
       // 当前非移动端,但是跳转了移动端路由
-      return next({ name: routerName.home });
+      console.log('当前非移动端,但是跳转了移动端路由');
+      if (to.name === mobileRouterName.h5Room) {
+        // 有可能是原生webrtc或srs-webrtc
+        return next({
+          name: routerName.home,
+        });
+      } else {
+        return next({
+          name: routerName.home,
+        });
+      }
     }
     return next();
   }

+ 3 - 5
src/utils/index.ts

@@ -1,7 +1,5 @@
 // TIP: ctrl+cmd+t,生成函数注释
 
-import { NODE_ENV } from 'script/constant';
-
 export const createVideo = ({ muted = true, autoplay = true }) => {
   const videoEl = document.createElement('video');
   videoEl.autoplay = autoplay;
@@ -14,9 +12,9 @@ export const createVideo = ({ muted = true, autoplay = true }) => {
   videoEl.oncontextmenu = (e) => {
     e.preventDefault();
   };
-  if (NODE_ENV === 'development') {
-    videoEl.controls = true;
-  }
+  // if (NODE_ENV === 'development') {
+  videoEl.controls = true;
+  // }
   return videoEl;
 };
 

+ 64 - 67
src/views/h5/room/index.vue

@@ -5,11 +5,11 @@
         <div
           class="avatar"
           :style="{
-            backgroundImage: `url(${liveRoomInfo?.user_live_room?.user.avatar})`,
+            backgroundImage: `url(${roomLiveing?.live?.user?.avatar})`,
           }"
         ></div>
         <div class="username">
-          {{ liveRoomInfo?.user_live_room?.user.username }}
+          {{ roomLiveing?.live?.user?.username }}
         </div>
       </div>
       <div class="right">
@@ -28,10 +28,14 @@
       <div
         class="cover"
         :style="{
-          backgroundImage: `url(${liveRoomInfo?.cover_img})`,
+          backgroundImage: `url(${roomLiveing?.live?.live_room?.cover_img})`,
         }"
       ></div>
-      <div ref="canvasRef"></div>
+      <div
+        ref="canvasRef"
+        class="media-list"
+        :class="{ item: appStore.allTrack.length > 1 }"
+      ></div>
       <div
         v-if="showPlayBtn"
         class="tip-btn"
@@ -46,6 +50,7 @@
       <div
         ref="containerRef"
         class="list"
+        :style="{ height: height + 'px' }"
       >
         <div
           v-for="(item, index) in damuList"
@@ -101,22 +106,19 @@ import { useRoute } from 'vue-router';
 import { fetchFindLiveRoom } from '@/api/liveRoom';
 import { useHlsPlay } from '@/hooks/use-play';
 import { usePull } from '@/hooks/use-pull';
-import {
-  DanmuMsgTypeEnum,
-  ILiveRoom,
-  LiveRoomTypeEnum,
-  liveTypeEnum,
-} from '@/interface';
+import { DanmuMsgTypeEnum, LiveRoomTypeEnum, liveTypeEnum } from '@/interface';
 import router, { mobileRouterName } from '@/router';
-import { videoToCanvas } from '@/utils';
+import { useAppStore } from '@/store/app';
 
 const route = useRoute();
+const appStore = useAppStore();
 
 const bottomRef = ref<HTMLDivElement>();
 const containerRef = ref<HTMLDivElement>();
 const canvasRef = ref<HTMLVideoElement>();
 const localVideoRef = ref<HTMLVideoElement[]>([]);
 const showPlayBtn = ref(false);
+const height = ref(0);
 
 const { hlsVideoEl, startHlsPlay } = useHlsPlay();
 
@@ -127,30 +129,18 @@ const {
   getSocketId,
   keydownDanmu,
   sendDanmu,
-  batchSendOffer,
-  startGetUserMedia,
-  startGetDisplayMedia,
-  addTrack,
   addVideo,
+  handleHlsPlay,
+  roomLiveType,
+  roomLiveing,
   autoplayVal,
   videoLoading,
-  balance,
-  roomLiveType,
-  roomSocketId,
-  roomName,
-  userName,
-  userAvatar,
-  currentLiveRoom,
-  hlsurl,
-  coverImg,
   roomNoLive,
   damuList,
-  giftList,
   liveUserList,
-  danmuStr,
-  localStream,
-  sender,
   sidebarList,
+  danmuStr,
+  liveRoomInfo,
 } = usePull({
   localVideoRef,
   canvasRef,
@@ -158,12 +148,6 @@ const {
   isSRS: false,
 });
 
-const liveRoomInfo = ref<ILiveRoom>();
-
-watch(
-  () => autoplayVal.value,
-  (v) => {}
-);
 watch(
   () => damuList.value.length,
   () => {
@@ -180,10 +164,10 @@ async function getLiveRoomInfo() {
     videoLoading.value = true;
     const res = await fetchFindLiveRoom(route.params.roomId as string);
     if (res.code === 200) {
-      liveRoomInfo.value = res.data;
+      console.log('kkkkk');
       if (res.data.type === LiveRoomTypeEnum.user_wertc) {
-        roomLiveType.value = liveTypeEnum.webrtcPull;
         autoplayVal.value = true;
+        roomLiveType.value = liveTypeEnum.webrtcPull;
         showPlayBtn.value = false;
       } else {
         showPlayBtn.value = true;
@@ -197,19 +181,9 @@ async function getLiveRoomInfo() {
   }
 }
 
-async function startPull() {
+function startPull() {
   showPlayBtn.value = false;
-  videoLoading.value = true;
-  const { width, height } = await startHlsPlay({
-    hlsurl: liveRoomInfo.value!.hls_url!,
-  });
-  videoToCanvas({
-    videoEl: hlsVideoEl.value!,
-    targetEl: canvasRef.value!,
-    width,
-    height,
-  });
-  videoLoading.value = false;
+  handleHlsPlay();
 }
 
 onMounted(() => {
@@ -219,7 +193,8 @@ onMounted(() => {
     const res =
       bottomRef.value.getBoundingClientRect().top -
       containerRef.value.getBoundingClientRect().top;
-    containerRef.value.style.height = `${res}px`;
+    height.value = res;
+    // containerRef.value.style.height = `${res}px`;
   }
 });
 </script>
@@ -269,26 +244,48 @@ onMounted(() => {
 
       inset: 0;
     }
-    :deep(video) {
-      position: absolute;
-      top: 0;
-      left: 50%;
-      width: 100%;
-      height: 100%;
-      transform: translate(-50%);
-
-      user-select: nones;
+    .media-list {
+      height: 230px;
+      overflow-y: scroll;
+      :deep(video) {
+        width: 100%;
+        height: 100%;
+      }
+      :deep(canvas) {
+        width: 100%;
+        height: 100%;
+      }
+      &.item {
+        :deep(video) {
+          width: 50%;
+          height: initial !important;
+        }
+        :deep(canvas) {
+          width: 50%;
+          height: initial !important;
+        }
+      }
     }
-    :deep(canvas) {
-      position: absolute;
-      top: 0;
-      left: 50%;
-      width: 100%;
-      height: 100%;
-      transform: translate(-50%);
+    // :deep(video) {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 50%;
+    //   width: 100%;
+    //   height: 100%;
+    //   transform: translate(-50%);
 
-      user-select: nones;
-    }
+    //   user-select: nones;
+    // }
+    // :deep(canvas) {
+    //   position: absolute;
+    //   top: 0;
+    //   left: 50%;
+    //   width: 100%;
+    //   height: 100%;
+    //   transform: translate(-50%);
+
+    //   user-select: nones;
+    // }
     .tip-btn {
       position: absolute;
       top: 50%;

+ 16 - 23
src/views/pull/index.vue

@@ -28,6 +28,7 @@
         <div
           ref="containerRef"
           class="container"
+          :style="{ height: height + 'px' }"
         >
           <div
             v-loading="videoLoading"
@@ -47,6 +48,7 @@
               ref="canvasRef"
               class="media-list"
               :class="{ item: appStore.allTrack.length > 1 }"
+              :style="{ height: height + 'px' }"
             ></div>
             <AudioRoomTip></AudioRoomTip>
             <VideoControls></VideoControls>
@@ -238,6 +240,7 @@ const userStore = useUserStore();
 const appStore = useAppStore();
 
 const giftGoodsList = ref<IGoods[]>([]);
+const height = ref(0);
 const giftLoading = ref(false);
 const showRecharge = ref(false);
 const showJoin = ref(true);
@@ -295,9 +298,10 @@ function handleRecharge() {
 }
 
 function handleJoin() {
+  window.$message.info('维护中~');
+  return;
   showJoin.value = !showJoin.value;
-  nextTick(async () => {
-    // await startGetUserMedia();
+  nextTick(() => {
     addVideo();
   });
 }
@@ -334,7 +338,7 @@ onMounted(() => {
       bottomRef.value.getBoundingClientRect().top -
       (topRef.value.getBoundingClientRect().top +
         topRef.value.getBoundingClientRect().height);
-    containerRef.value.style.height = `${res}px`;
+    height.value = res;
   }
   initPull();
 });
@@ -430,37 +434,26 @@ onMounted(() => {
           inset: 0;
         }
         .media-list {
+          overflow-y: scroll;
           :deep(video) {
             width: 100%;
             height: 100%;
           }
+          :deep(canvas) {
+            width: 100%;
+            height: 100%;
+          }
           &.item {
             :deep(video) {
               width: 50%;
               height: initial !important;
             }
+            :deep(canvas) {
+              width: 50%;
+              height: initial !important;
+            }
           }
         }
-        // :deep(canvas) {
-        //   position: absolute;
-        //   top: 0;
-        //   left: 50%;
-        //   width: 100%;
-        //   height: 100%;
-        //   transform: translate(-50%);
-
-        //   user-select: none;
-        // }
-        // :deep(video) {
-        //   position: absolute;
-        //   top: 0;
-        //   left: 50%;
-        //   width: 100%;
-        //   height: 100%;
-        //   transform: translate(-50%);
-
-        //   user-select: none;
-        // }
 
         .controls {
           display: none;

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

@@ -395,6 +395,13 @@ async function addMediaOk(val: {
       addTrack(videoTrack);
       addTrack(autioTrack);
     } else {
+      if (
+        isSRS &&
+        appStore.allTrack.filter((item) => item.video === 1).length >= 1
+      ) {
+        window.$message.error('srs模式最多只能有一个视频');
+        return;
+      }
       appStore.setAllTrack([...appStore.allTrack, videoTrack]);
       addTrack(videoTrack);
     }
@@ -409,6 +416,13 @@ async function addMediaOk(val: {
       },
       audio: false,
     });
+    if (
+      isSRS &&
+      appStore.allTrack.filter((item) => item.video === 1).length >= 1
+    ) {
+      window.$message.error('srs模式最多只能有一个视频');
+      return;
+    }
     const track = {
       id: getRandomString(8),
       audio: 2,
@@ -499,11 +513,19 @@ function handleStartMedia(item: { type: MediaTypeEnum; txt: string }) {
             width: 100%;
             height: 100%;
           }
+          :deep(canvas) {
+            width: 100%;
+            height: 100%;
+          }
           &.item {
             :deep(video) {
               width: 50%;
               height: initial !important;
             }
+            :deep(canvas) {
+              width: 50%;
+              height: initial !important;
+            }
           }
         }