Bladeren bron

fix: 修补已知bug

shuisheng 2 jaren geleden
bovenliggende
commit
a3b77286ba

+ 3 - 2
src/api/srs.ts

@@ -1,3 +1,4 @@
+import { SRS_STREAM_URL } from '@/constant';
 import request from '@/utils/request';
 
 export function fetchRtcV1Publish(data: {
@@ -8,7 +9,7 @@ export function fetchRtcV1Publish(data: {
   tid: string;
 }) {
   return request.instance({
-    baseURL: '/srs',
+    baseURL: SRS_STREAM_URL,
     url: `/rtc/v1/publish/`,
     method: 'post',
     data,
@@ -22,7 +23,7 @@ export function fetchRtcV1Play(data: {
   tid: string;
 }) {
   return request.instance({
-    baseURL: '/srs',
+    baseURL: SRS_STREAM_URL,
     url: '/rtc/v1/play/',
     method: 'post',
     data,

+ 63 - 11
src/components/VideoControls/index.vue

@@ -1,16 +1,32 @@
 <template>
   <div class="video-controls-wrap">
-    <div
-      class="item"
-      @click="appStore.setMuted(!appStore.muted)"
-    >
-      <n-icon
-        size="25"
-        color="white"
+    <div class="left">
+      <div
+        class="item"
+        @click="appStore.setMuted(!appStore.muted)"
       >
-        <VolumeMuteOutline v-if="appStore.muted"></VolumeMuteOutline>
-        <VolumeHighOutline v-else></VolumeHighOutline>
-      </n-icon>
+        <n-icon
+          size="25"
+          color="white"
+        >
+          <VolumeMuteOutline v-if="appStore.muted"></VolumeMuteOutline>
+          <VolumeHighOutline v-else></VolumeHighOutline>
+        </n-icon>
+      </div>
+    </div>
+
+    <div class="right">
+      <div class="speed">
+        <span class="txt">倍速</span>
+        <div class="list">
+          <div class="iten">2.0x</div>
+          <div class="iten">1.5x</div>
+          <div class="iten">1.25x</div>
+          <div class="iten">1.0x</div>
+          <div class="iten">0.75x</div>
+          <div class="iten">0.5x</div>
+        </div>
+      </div>
     </div>
   </div>
 </template>
@@ -31,7 +47,7 @@ const appStore = useAppStore();
   display: flex;
   align-items: center;
   box-sizing: border-box;
-  padding-left: 10px;
+  padding: 0 20px 0 10px;
   width: 100%;
   z-index: 1;
   height: 40px;
@@ -41,9 +57,45 @@ const appStore = useAppStore();
     rgba(0, 0, 0, 0),
     rgba(0, 0, 0, 0.6)
   );
+  color: white;
   text-align: initial;
+  justify-content: space-between;
   .item {
     cursor: pointer;
   }
+  .left {
+  }
+  .right {
+    .speed {
+      position: relative;
+      &:hover {
+        .list {
+          display: block;
+        }
+      }
+      .txt {
+        cursor: pointer;
+      }
+      .list {
+        position: absolute;
+        left: 50%;
+        top: 0;
+        text-align: center;
+        display: none;
+        background-color: rgba($color: #000000, $alpha: 0.5);
+        transform: translate(-50%, -100%);
+        .iten {
+          padding: 6px 10px;
+          &:not(:last-child) {
+            margin-bottom: 4px;
+          }
+          &:hover {
+            background-color: rgba($color: #ffffff, $alpha: 0.1);
+            cursor: pointer;
+          }
+        }
+      }
+    }
+  }
 }
 </style>

+ 10 - 0
src/constant.ts

@@ -5,6 +5,16 @@ export const QQ_REDIRECT_URI = 'https://live.hsslive.cn/oauth/qq_login';
 export const AUTHOR_GITHUB = 'https://github.com/galaxy-s10';
 export const LIVE_CLIENT_URL = 'https://live.hsslive.cn';
 
+export const SRS_STREAM_URL =
+  process.env.NODE_ENV === 'development'
+    ? 'http://localhost:1985'
+    : 'https://srs-pull.hsslive.cn/srs';
+
+export const WEBSOCKET_URL =
+  process.env.NODE_ENV === 'development'
+    ? 'ws://localhost:4300'
+    : 'wss://srs-pull.hsslive.cn';
+
 export const APIFOX_URL =
   'https://apifox.com/apidoc/shared-c7556b54-17b2-494e-a039-572d83f103ed/';
 

+ 39 - 31
src/hooks/use-play.ts

@@ -1,4 +1,5 @@
 import '@/assets/css/videojs.scss';
+import { isSafari } from 'billd-utils';
 import flvJs from 'flv.js';
 import videoJs from 'video.js';
 import Player from 'video.js/dist/types/player';
@@ -34,8 +35,9 @@ export function useFlvPlay() {
   );
 
   function setMuted(val) {
+    console.log(val, '--------');
     if (flvPlayer.value) {
-      flvPlayer.value.muted = val;
+      // flvPlayer.value.muted = val;
     }
     if (flvVideoEl.value) {
       flvVideoEl.value.muted = val;
@@ -45,38 +47,43 @@ export function useFlvPlay() {
   function startFlvPlay(data: { flvurl: string }) {
     destroyFlv();
     return new Promise<{ width: number; height: number }>((resolve) => {
-      if (flvJs.isSupported()) {
-        flvPlayer.value = flvJs.createPlayer({
-          type: 'flv',
-          url: data.flvurl,
-        });
-        const videoEl = document.createElement('video');
-        videoEl.muted = true;
-        videoEl.playsInline = true;
-        videoEl.setAttribute('webkit-playsinline', 'true');
-        flvVideoEl.value = videoEl;
-        flvVideoEl.value.addEventListener('play', () => {
-          console.log('flv-play');
-        });
-        flvVideoEl.value.addEventListener('playing', () => {
-          console.log('flv-playing');
-          resolve({
-            width: flvVideoEl.value?.videoWidth || 0,
-            height: flvVideoEl.value?.videoHeight || 0,
+      setTimeout(() => {
+        if (flvJs.isSupported()) {
+          flvPlayer.value = flvJs.createPlayer({
+            type: 'flv',
+            url: data.flvurl,
           });
-        });
-        flvPlayer.value.attachMediaElement(flvVideoEl.value);
-        flvPlayer.value.load();
-        try {
-          console.log('开始播放flv播放');
-          flvPlayer.value.play();
-        } catch (err) {
-          console.error('flv播放失败');
-          console.log(err);
+          const videoEl = document.createElement('video');
+          // videoEl.autoplay = true;
+          videoEl.muted = true;
+          videoEl.playsInline = true;
+          videoEl.setAttribute('webkit-playsinline', 'true');
+          flvVideoEl.value = videoEl;
+          flvVideoEl.value.addEventListener('play', () => {
+            console.log('flv-play');
+          });
+          flvVideoEl.value.addEventListener('playing', () => {
+            console.log('flv-playing', isSafari());
+            setMuted(appStore.muted);
+
+            resolve({
+              width: flvVideoEl.value?.videoWidth || 0,
+              height: flvVideoEl.value?.videoHeight || 0,
+            });
+          });
+          flvPlayer.value.attachMediaElement(flvVideoEl.value);
+          flvPlayer.value.load();
+          try {
+            console.log('开始播放flv播放');
+            flvPlayer.value.play();
+          } catch (err) {
+            console.error('flv播放失败');
+            console.log(err);
+          }
+        } else {
+          console.error('不支持flv');
         }
-      } else {
-        console.error('不支持flv');
-      }
+      }, 500);
     });
   }
 
@@ -120,6 +127,7 @@ export function useHlsPlay() {
   function startHlsPlay(data: { hlsurl: string }) {
     destroyHls();
     const videoEl = document.createElement('video');
+    videoEl.autoplay = true;
     videoEl.muted = true;
     videoEl.playsInline = true;
     videoEl.setAttribute('webkit-playsinline', 'true');

+ 7 - 10
src/hooks/use-pull.ts

@@ -3,6 +3,7 @@ import { Ref, nextTick, onUnmounted, reactive, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 
 import { fetchRtcV1Play } from '@/api/srs';
+import { SRS_STREAM_URL, WEBSOCKET_URL } from '@/constant';
 import { useFlvPlay, useHlsPlay } from '@/hooks/use-play';
 import {
   DanmuMsgTypeEnum,
@@ -196,10 +197,7 @@ export function usePull({
     console.warn('开始new WebSocketClass');
     const ws = new WebSocketClass({
       roomId: roomId.value,
-      url:
-        process.env.NODE_ENV === 'development'
-          ? 'ws://localhost:4300'
-          : 'wss://live.hsslive.cn',
+      url: WEBSOCKET_URL,
       isAnchor: false,
     });
     ws.update();
@@ -215,7 +213,10 @@ export function usePull({
 
     remoteVideoRef.value?.addEventListener('loadedmetadata', () => {
       console.warn('视频流-loadedmetadata');
-      if (liveType === liveTypeEnum.webrtcPull) {
+      if (
+        liveType === liveTypeEnum.webrtcPull ||
+        liveType === liveTypeEnum.srsWebrtcPull
+      ) {
         canvasRef.value?.appendChild(remoteVideoRef.value);
       }
       videoLoading.value = false;
@@ -390,11 +391,7 @@ export function usePull({
         if (!offer) return;
         await rtc.setLocalDescription(offer);
         const res: any = await fetchRtcV1Play({
-          api: `${
-            process.env.NODE_ENV === 'development'
-              ? 'http://localhost:1985'
-              : 'https://live.hsslive.cn/srs'
-          }/rtc/v1/play/`,
+          api: `${SRS_STREAM_URL}/rtc/v1/play/`,
           clientip: null,
           sdp: offer.sdp!,
           streamurl: streamurl.value,

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

@@ -15,6 +15,7 @@ import {
   fetchCreateUserLiveRoom,
   fetchUserHasLiveRoom,
 } from '@/api/userLiveRoom';
+import { SRS_STREAM_URL, WEBSOCKET_URL } from '@/constant';
 import {
   DanmuMsgTypeEnum,
   IAnswer,
@@ -71,7 +72,6 @@ export function usePush({
     video: 1,
   });
   const streamurl = ref('');
-  const flvurl = ref('');
 
   const damuList = ref<IDanmu[]>([]);
   const liveUserList = ref<ILiveUser[]>([]);
@@ -118,11 +118,6 @@ export function usePush({
 
   onMounted(() => {
     roomId.value = route.query.roomId as string;
-    flvurl.value = `${
-      process.env.NODE_ENV === 'development'
-        ? 'http://localhost:5001'
-        : 'https://live.hsslive.cn/srsflv'
-    }/livestream/roomId___${roomId.value}.flv`;
     if (!loginTip()) return;
   });
 
@@ -184,10 +179,7 @@ export function usePush({
     disabled.value = true;
     const instance = new WebSocketClass({
       roomId: roomId.value,
-      url:
-        process.env.NODE_ENV === 'development'
-          ? 'ws://localhost:4300'
-          : 'wss://live.hsslive.cn',
+      url: WEBSOCKET_URL,
       isAnchor: true,
     });
     instance.update();
@@ -220,11 +212,7 @@ export function usePush({
         if (!offer) return;
         await rtc.setLocalDescription(offer);
         const res: any = await fetchRtcV1Publish({
-          api: `${
-            process.env.NODE_ENV === 'development'
-              ? 'http://localhost:1985'
-              : 'https://live.hsslive.cn/srs'
-          }/rtc/v1/publish/`,
+          api: `${SRS_STREAM_URL}/rtc/v1/publish/`,
           clientip: null,
           sdp: offer.sdp!,
           streamurl: userStore.userInfo!.live_rooms![0]!.rtmp_url!.replace(

+ 2 - 3
src/layout/pc/modal/index.vue

@@ -29,11 +29,10 @@
 import { openToTarget } from 'billd-utils';
 import { ref } from 'vue';
 
-import router, { routerName } from '@/router';
 // const showModal = ref(process.env.NODE_ENV === 'production');
-// const showModal = ref(false);
+const showModal = ref(false);
 // const showModal = ref(true);
-const showModal = ref(router.currentRoute.value.name === routerName.home);
+// const showModal = ref(router.currentRoute.value.name === routerName.home);
 </script>
 
 <style lang="scss" scoped>

+ 0 - 2
src/utils/index.ts

@@ -26,8 +26,6 @@ export function videoToCanvas(data: {
   height: number;
 }) {
   const { videoEl, targetEl, width, height } = data;
-  console.warn('videoToCanvas', videoEl, targetEl, width, height);
-
   if (!videoEl || !targetEl) {
     return;
   }

+ 5 - 8
src/views/h5/room/index.vue

@@ -184,6 +184,8 @@ async function getLiveRoomInfo() {
 
 async function startPull() {
   showPlayBtn.value = false;
+  videoLoading.value = true;
+
   const { width, height } = await startHlsPlay({
     hlsurl: liveRoomInfo.value!.hls_url!,
   });
@@ -193,6 +195,7 @@ async function startPull() {
     width,
     height,
   });
+  videoLoading.value = false;
 }
 
 onMounted(() => {
@@ -252,20 +255,14 @@ onMounted(() => {
 
       inset: 0;
     }
-    // :deep(video) {
-    //   position: absolute;
-    //   top: 0;
-    //   left: 50%;
-    //   width: 100%;
-    //   height: 100%;
-    //   transform: translate(-50%);
-    // }
     :deep(canvas) {
       position: absolute;
       top: 0;
       left: 50%;
       height: 100%;
       transform: translate(-50%);
+
+      user-select: nones;
     }
     .tip-btn {
       position: absolute;

+ 8 - 12
src/views/home/index.vue

@@ -22,14 +22,7 @@
           ref="canvasRef"
         ></div>
         <template v-if="currentLiveRoom">
-          <div
-            class="controls"
-            :style="{
-              display: !isMobile() ? 'none' : showControls ? 'block' : 'none',
-            }"
-          >
-            <VideoControls></VideoControls>
-          </div>
+          <VideoControls></VideoControls>
           <div
             class="join-btn"
             :style="{
@@ -216,7 +209,7 @@ onMounted(() => {
   getLiveRoomList();
 });
 
-function joinRoom() {
+async function joinRoom() {
   if (currentLiveRoom.value?.live_room?.type === LiveRoomTypeEnum.user_srs) {
     router.push({
       name: routerName.pull,
@@ -295,6 +288,7 @@ function joinHlsRoom() {
         left: 50%;
         height: 100%;
         transform: translate(-50%);
+        user-select: none;
       }
       :deep(video) {
         position: absolute;
@@ -303,6 +297,7 @@ function joinHlsRoom() {
         width: 100%;
         height: 100%;
         transform: translate(-50%);
+        user-select: none;
       }
       .controls {
         display: none;
@@ -312,15 +307,16 @@ function joinHlsRoom() {
         .join-btn {
           display: inline-flex !important;
         }
-        .controls {
-          display: block !important;
-        }
       }
       .join-btn {
         position: absolute;
         top: 50%;
         left: 50%;
         z-index: 1;
+        width: 100%;
+        box-sizing: border-box;
+        align-items: center;
+        justify-content: center;
         display: none;
         align-items: center;
         transform: translate(-50%, -50%);

+ 12 - 19
src/views/pull/index.vue

@@ -50,14 +50,7 @@
             >
               点击播放
             </div>
-            <div
-              class="controls"
-              :style="{
-                display: !isMobile() ? 'none' : showControls ? 'block' : 'none',
-              }"
-            >
-              <VideoControls></VideoControls>
-            </div>
+            <VideoControls></VideoControls>
           </div>
 
           <div
@@ -216,7 +209,6 @@
 </template>
 
 <script lang="ts" setup>
-import { isMobile } from 'billd-utils';
 import { nextTick, onMounted, onUnmounted, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 
@@ -290,6 +282,7 @@ const { hlsVideoEl, startHlsPlay } = useHlsPlay();
 
 async function startPull() {
   showPlayBtn.value = false;
+  videoLoading.value = true;
   const res = await startHlsPlay({
     hlsurl: hlsurl.value,
   });
@@ -299,6 +292,7 @@ async function startPull() {
     width: res.width,
     height: res.height,
   });
+  videoLoading.value = false;
 }
 
 async function getGoodsList() {
@@ -463,20 +457,25 @@ onMounted(() => {
 
           inset: 0;
         }
-        :deep(video) {
+        :deep(canvas) {
           position: absolute;
           top: 0;
-          left: 0;
-          width: 100%;
+          left: 50%;
           height: 100%;
+          transform: translate(-50%);
+
+          user-select: none;
         }
-        :deep(canvas) {
+        :deep(video) {
           position: absolute;
           top: 0;
           left: 50%;
           height: 100%;
           transform: translate(-50%);
+
+          user-select: none;
         }
+
         .controls {
           display: none;
         }
@@ -498,12 +497,6 @@ onMounted(() => {
             color: white;
           }
         }
-
-        &:hover {
-          .controls {
-            display: block !important;
-          }
-        }
       }
       .sidebar {
         width: 120px;

+ 1 - 14
src/views/push/index.vue

@@ -21,12 +21,7 @@
             x5-video-orientation="portraint"
             muted
           ></video>
-          <div
-            v-if="currMediaTypeList.length > 0"
-            class="controls"
-          >
-            <VideoControls></VideoControls>
-          </div>
+          <VideoControls v-if="currMediaTypeList.length > 0"></VideoControls>
           <div
             v-if="!currMediaTypeList || currMediaTypeList.length <= 0"
             class="add-wrap"
@@ -301,14 +296,6 @@ onMounted(() => {
           max-width: 100%;
           max-height: 100%;
         }
-        .controls {
-          display: none;
-        }
-        &:hover {
-          .controls {
-            display: block;
-          }
-        }
         .add-wrap {
           position: absolute;
           top: 50%;