Quellcode durchsuchen

feat: 全面优化

shuisheng vor 1 Jahr
Ursprung
Commit
a39752c2fd
46 geänderte Dateien mit 269 neuen und 261 gelöschten Zeilen
  1. 1 1
      README.md
  2. 2 2
      doc/备忘.md
  3. 2 2
      package.json
  4. 9 9
      pnpm-lock.yaml
  5. 29 0
      script/config/webpack.common.ts
  6. 1 1
      script/constant.ts
  7. 4 4
      src/App.vue
  8. 1 0
      src/api/area.ts
  9. 0 66
      src/api/emailUser.ts
  10. 1 0
      src/api/giftRecord.ts
  11. 1 0
      src/api/liveRoom.ts
  12. 1 0
      src/api/qiniuData.ts
  13. 1 0
      src/api/user.ts
  14. 1 0
      src/api/wallet.ts
  15. 2 1
      src/hooks/tipModal/index.vue
  16. 8 0
      src/hooks/use-common.ts
  17. 4 4
      src/hooks/use-play.ts
  18. 7 56
      src/hooks/use-pull.ts
  19. 1 5
      src/hooks/use-push.ts
  20. 1 4
      src/hooks/use-rtcParams.ts
  21. 1 1
      src/hooks/use-tip.ts
  22. 15 53
      src/hooks/use-websocket.ts
  23. 1 1
      src/hooks/webrtc/live.ts
  24. 1 1
      src/hooks/webrtc/meetingOne.ts
  25. 1 1
      src/hooks/webrtc/meetingPk.ts
  26. 1 1
      src/hooks/webrtc/meetingTwo.ts
  27. 1 3
      src/hooks/webrtc/srs.ts
  28. 15 1
      src/layout/pc/head/index.vue
  29. 11 4
      src/router/index.ts
  30. 0 1
      src/store/app/index.ts
  31. 2 2
      src/store/network/index.ts
  32. 4 4
      src/utils/index.ts
  33. 0 0
      src/utils/network/webRTC.ts
  34. 0 0
      src/utils/network/webSocket.ts
  35. 2 0
      src/views/about/faq/index.vue
  36. 0 0
      src/views/about/group/index.vue
  37. 128 0
      src/views/about/pushStreamDifferent/index.vue
  38. 2 0
      src/views/about/release/index.vue
  39. 0 0
      src/views/about/team/index.vue
  40. 2 0
      src/views/privatizationDeployment/index.vue
  41. 1 1
      src/views/profile/index.vue
  42. 0 1
      src/views/pull/index.vue
  43. 0 1
      src/views/pull/recharge/index.vue
  44. 2 29
      src/views/push/index.vue
  45. 0 1
      src/views/shop/index.vue
  46. 2 0
      src/views/sponsors/index.vue

+ 1 - 1
README.md

@@ -187,7 +187,7 @@ pnpm i
 > 更新 billd 相关依赖:
 
 ```bash
-pnpm i billd-utils@latest billd-scss@latest billd-html-webpack-plugin@latest
+pnpm i billd-utils@latest billd-scss@latest billd-deploy@latest billd-html-webpack-plugin@latest
 ```
 
 - 运行

+ 2 - 2
doc/备忘.md

@@ -11,8 +11,8 @@
   > 优点:实现简单;缺点:主播断开后,所有观众都会跟着断开。
 - webrtc会议实现二
   > 在roomLiving的时候,每个人都给除自己以外的所有人发offer,并和除自己以外的所有人进行视频通话,将收到的流进行展示
-  > 有主播和2个观众,结果就是画面是所有人的画面,主播new了2个rtc,每个观众各自new了一个rtc
-  > 优点:所有视频通话都是独立的,一个断开不会影响另一个;缺点:实现起来稍微麻烦一点。
+  > 房间里有3个人,结果就是画面是所有人的画面,每个人都有2个rtc
+  > 优点:所有视频通话都是独立的,一个断开不会影响另一个;缺点:实现起来稍微麻烦一点,并且因为客户端存在n个rtc,因此对客户端带宽压力更大
 - 打pk
   > 主播和其他人先webrtc视频通话,再由任意一方转推srs。
 - 腾讯云云直播

+ 2 - 2
package.json

@@ -37,8 +37,8 @@
   "dependencies": {
     "@vicons/ionicons5": "^0.12.0",
     "axios": "^1.2.1",
-    "billd-deploy": "^1.0.21",
-    "billd-html-webpack-plugin": "^1.0.5",
+    "billd-deploy": "^1.0.23",
+    "billd-html-webpack-plugin": "^1.0.6",
     "billd-scss": "^0.0.8",
     "billd-utils": "^0.0.22",
     "fabric": "^5.3.0",

+ 9 - 9
pnpm-lock.yaml

@@ -12,11 +12,11 @@ dependencies:
     specifier: ^1.2.1
     version: 1.3.4
   billd-deploy:
-    specifier: ^1.0.21
-    version: 1.0.21(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
+    specifier: ^1.0.23
+    version: 1.0.23(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
   billd-html-webpack-plugin:
-    specifier: ^1.0.5
-    version: 1.0.5(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
+    specifier: ^1.0.6
+    version: 1.0.6(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
   billd-scss:
     specifier: ^0.0.8
     version: 0.0.8
@@ -3846,12 +3846,12 @@ packages:
     resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
     dev: true
 
-  /billd-deploy@1.0.21(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0):
-    resolution: {integrity: sha512-xFcfHnOJPlJxj+wDhMpHqHFBM79cxiXC5i4vqrfztT6kz1QBJpK/Rh8bY7PCq8Kngk+5oSjNSew19SSbONnxgg==}
+  /billd-deploy@1.0.23(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0):
+    resolution: {integrity: sha512-Ouih/nYp3lY1qt6GHUtQbMm3w3yPjxD+4ShpwWU+5iJfIqdC3KY7AoC5lu2QCa4KD7NG9qHpn6aYEiyWJmB1vQ==}
     requiresBuild: true
     dependencies:
       ali-oss: 6.20.0
-      billd-html-webpack-plugin: 1.0.5(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
+      billd-html-webpack-plugin: 1.0.6(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0)
       cos-nodejs-sdk-v5: 2.13.1
       esdk-obs-nodejs: 3.23.11
       inquirer: 8.2.5
@@ -3873,8 +3873,8 @@ packages:
       - webpack-cli
     dev: false
 
-  /billd-html-webpack-plugin@1.0.5(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0):
-    resolution: {integrity: sha512-SYT/tR7+LcnCc3kADU7Lt56HDPKCBOo0R1QNj4ky78aGqH4BqOUMqbe66uIjqa4MqFHsWYjkOarO7JY4M/KpYw==}
+  /billd-html-webpack-plugin@1.0.6(@swc/core@1.3.84)(@types/node@18.15.3)(esbuild@0.15.18)(sass@1.59.3)(terser@5.16.6)(webpack-cli@4.10.0):
+    resolution: {integrity: sha512-zM294oAMqRD1rlqoyC1E9QbFsBgMPYStODmQKwUjI+xd02Rwo+3iZhmlQ8q0EuF2KnyhwDwhxyZfDGSo6Ow8Tw==}
     requiresBuild: true
     dependencies:
       vite: 4.2.0(@types/node@18.15.3)(sass@1.59.3)(terser@5.16.6)

+ 29 - 0
script/config/webpack.common.ts

@@ -2,6 +2,7 @@ import FriendlyErrorsWebpackPlugin from '@soda/friendly-errors-webpack-plugin';
 import BilldHtmlWebpackPlugin, { logData } from 'billd-html-webpack-plugin';
 import CopyWebpackPlugin from 'copy-webpack-plugin';
 import ESLintPlugin from 'eslint-webpack-plugin';
+import ForkTsCheckerWebpackPlugin from 'fork-ts-checker-webpack-plugin';
 import HtmlWebpackPlugin from 'html-webpack-plugin';
 import MiniCssExtractPlugin from 'mini-css-extract-plugin';
 import { NaiveUiResolver } from 'unplugin-vue-components/resolvers';
@@ -276,6 +277,34 @@ const commonConfig = (isProduction) => {
       webpackBarEnable && new WebpackBar(),
       // 友好的显示错误信息在终端
       new FriendlyErrorsWebpackPlugin(),
+      new ForkTsCheckerWebpackPlugin({
+        // https://github.com/TypeStrong/fork-ts-checker-webpack-plugin
+        typescript: {
+          // extensions: {
+          //   vue: {
+          //     enabled: true,
+          //     compiler: resolveApp('./node_modules/vue/compiler-sfc/index.js'),
+          //   },
+          // },
+          diagnosticOptions: {
+            semantic: true,
+            syntactic: false,
+          },
+        },
+        /**
+         * devServer如果设置为false,则不会向 Webpack Dev Server 报告错误。
+         * 但是控制台还是会打印错误。
+         */
+        devServer: false, // 7.x版本:https://github.com/TypeStrong/fork-ts-checker-webpack-plugin/issues/723
+        // logger: {
+        //   devServer: false, // fork-ts-checker-webpack-plugin6.x版本
+        // },
+        /**
+         * async 为 false,同步的将错误信息反馈给 webpack,如果报错了,webpack 就会编译失败
+         * async 默认为 true,异步的将错误信息反馈给 webpack,如果报错了,不影响 webpack 的编译
+         */
+        async: true,
+      }),
       // 解析vue
       new VueLoaderPlugin(),
       // eslint-disable-next-line

+ 1 - 1
script/constant.ts

@@ -13,7 +13,7 @@ export const htmlWebpackPluginTitle = 'billd-live'; // htmlWebpackPlugin的标
 
 export const outputStaticUrl = (isProduction: boolean) => {
   if (isProduction) {
-    return 'https://resource.hsslive.cn/billd-live/client/';
+    return 'https://resource.hsslive.cn/billd-live/client/dist/';
   }
   return '/';
 };

+ 4 - 4
src/App.vue

@@ -18,14 +18,14 @@ import { GlobalThemeOverrides, NConfigProvider } from 'naive-ui';
 import { onMounted } from 'vue';
 
 import { THEME_COLOR } from '@/constant';
-import { useCheckUpdate } from '@/hooks/use-checkUpdate';
+import { useBuildInfo } from '@/hooks/use-common';
 import { loginMessage } from '@/hooks/use-login';
 import { usePiniaCacheStore } from '@/store/cache';
 import { useUserStore } from '@/store/user';
 import { getLastBuildDate, setLastBuildDate } from '@/utils/localStorage/app';
 import { getToken } from '@/utils/localStorage/user';
 
-const { appInfo } = useCheckUpdate();
+const { info } = useBuildInfo();
 const cacheStore = usePiniaCacheStore();
 const userStore = useUserStore();
 
@@ -64,10 +64,10 @@ onMounted(() => {
 
 function handleUpdate() {
   const old = getLastBuildDate();
-  if (appInfo.value.lastBuildDate !== old) {
+  if (info.value.lastBuildDate !== old) {
     localStorage.clear();
   }
-  setLastBuildDate(appInfo.value.lastBuildDate);
+  setLastBuildDate(info.value.lastBuildDate);
 }
 </script>
 

+ 1 - 0
src/api/area.ts

@@ -5,6 +5,7 @@ import request from '@/utils/request';
 export function fetchAreaList() {
   return request.get('/area/list');
 }
+
 export function fetchAreaLiveRoomList(params) {
   return request.get('/area/area_live_room_list', {
     params,

+ 0 - 66
src/api/emailUser.ts

@@ -1,66 +0,0 @@
-import request from '@/utils/request';
-
-export function fetchEmailUserList(params) {
-  return request.get('/email_user/list', {
-    params,
-  });
-}
-
-// 发送邮箱登录验证码登录
-export function fetchSendLoginCode(email) {
-  return request.post('/email_user/send_login_code', {
-    email,
-  });
-}
-
-// 邮箱验证码登录
-export function fetchEmailCodeLogin({ email, code }) {
-  return request.post('/email_user/login', {
-    email,
-    code,
-  });
-}
-
-// 发送邮箱注册验证码登录
-export function fetchSendRegisterCode(email) {
-  return request.post('/email_user/send_register_code', {
-    email,
-  });
-}
-
-/** 注册 */
-export function fetchRegister({ email, code }) {
-  return request.post('/email_user/register', {
-    email,
-    code,
-  });
-}
-
-// 绑定邮箱
-export function fetchBindEmail({ email, code }) {
-  return request.post('/email_user/bind_email', {
-    email,
-    code,
-  });
-}
-
-// 发送绑定邮箱验证码
-export function fetchSendBindEmailCode(email) {
-  return request.post('/email_user/send_bind_code', {
-    email,
-  });
-}
-
-// 取消绑定邮箱
-export function fetchCancelBindEmail(code) {
-  return request.post('/email_user/cancel_bind_email', {
-    code,
-  });
-}
-
-// 发送取消绑定邮箱验证码
-export function fetchCancelSendBindEmailCode(email) {
-  return request.post('/email_user/send_cancel_bind_code', {
-    email,
-  });
-}

+ 1 - 0
src/api/giftRecord.ts

@@ -11,6 +11,7 @@ export function fetchGiftGroupList(params: IList<IGiftRecord>) {
     },
   });
 }
+
 export function fetchGiftRecordList(params: IList<IGiftRecord>) {
   return request.get<IPaging<IGiftRecord>>('/gift_record/list', {
     params: {

+ 1 - 0
src/api/liveRoom.ts

@@ -13,6 +13,7 @@ export function fetchVerifyPkKey(data: { liveRoomId: number; key }) {
     params: { key: data.key },
   });
 }
+
 export function fetchUpdateLiveRoomKey() {
   return request.instance({
     url: '/live_room/update_key',

+ 1 - 0
src/api/qiniuData.ts

@@ -12,6 +12,7 @@ export function fetchQiniuDataList(params) {
     params,
   });
 }
+
 export function fetchDiff(params) {
   return request.get('/qiniu_data/diff', {
     params,

+ 1 - 0
src/api/user.ts

@@ -39,6 +39,7 @@ export function fetchLogin({ id, password }) {
 export function fetchUserInfo() {
   return request.get<IUser>('/user/get_user_info');
 }
+
 export function fetchFindUser(userId: number) {
   return request.get(`/user/find/${userId}`);
 }

+ 1 - 0
src/api/wallet.ts

@@ -6,6 +6,7 @@ export function fetchWalletList(params) {
     params,
   });
 }
+
 export function fetchMyWallet() {
   return request.get<IWallet>('/wallet/my_wallet');
 }

+ 2 - 1
src/hooks/modal/index.vue → src/hooks/tipModal/index.vue

@@ -6,6 +6,7 @@
     <Modal
       :title="title"
       :mask-closable="maskClosable"
+      :hidden-close="hiddenClose"
       @close="handleCancel()"
       :width="width"
     >
@@ -36,7 +37,7 @@
 import { VNode, defineComponent, ref, render, watch } from 'vue';
 
 export default defineComponent({
-  name: 'modal',
+  name: 'tipModal',
   emits: ['ok', 'cancel'],
   setup() {
     const title = ref('');

+ 8 - 0
src/hooks/use-checkUpdate.ts → src/hooks/use-common.ts

@@ -9,3 +9,11 @@ export const useCheckUpdate = () => {
   );
   return { appInfo };
 };
+
+export const useBuildInfo = () => {
+  const info = ref<BilldHtmlWebpackPluginLog>(
+    // @ts-ignore
+    process.env.BilldHtmlWebpackPlugin as BilldHtmlWebpackPluginLog
+  );
+  return { info };
+};

+ 4 - 4
src/hooks/use-play.ts

@@ -175,9 +175,9 @@ export function useFlvPlay() {
           try {
             console.log(`开始播放flv,muted:${cacheStore.muted}`);
             flvPlayer.value.play();
-          } catch (err) {
+          } catch (error) {
             console.error('flv播放失败');
-            console.log(err);
+            console.log(error);
           }
         } else {
           console.error('不支持flv');
@@ -286,9 +286,9 @@ export function useHlsPlay() {
             try {
               // console.log(`开始播放hls,muted:${cacheStore.muted}`);
               hlsPlayer.value?.play();
-            } catch (err) {
+            } catch (error) {
               console.error('hls播放失败');
-              console.log(err);
+              console.log(error);
             }
           }
         );

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

@@ -1,5 +1,6 @@
 import { getRandomString } from 'billd-utils';
 import { onUnmounted, ref, watch } from 'vue';
+import { useRoute } from 'vue-router';
 
 import { commentAuthTip, loginTip } from '@/hooks/use-login';
 import { useFlvPlay, useHlsPlay } from '@/hooks/use-play';
@@ -12,13 +13,12 @@ import {
 import { useAppStore } from '@/store/app';
 import { usePiniaCacheStore } from '@/store/cache';
 import { useNetworkStore } from '@/store/network';
-import { useUserStore } from '@/store/user';
 import { ILiveRoom, LiveRoomTypeEnum } from '@/types/ILiveRoom';
 import { WsMessageType, WsMsgTypeEnum } from '@/types/websocket';
 import { createVideo, videoToCanvas } from '@/utils';
 
 export function usePull(roomId: string) {
-  const userStore = useUserStore();
+  const route = useRoute();
   const networkStore = useNetworkStore();
   const cacheStore = usePiniaCacheStore();
   const appStore = useAppStore();
@@ -33,15 +33,9 @@ export function usePull(roomId: string) {
   const hlsurl = ref('');
   const videoWrapRef = ref<HTMLDivElement>();
   const videoHeight = ref();
-  const sidebarList = ref<
-    {
-      socketId: string;
-    }[]
-  >([]);
   const videoElArr = ref<HTMLVideoElement[]>([]);
   const remoteVideo = ref<HTMLElement[]>([]);
   const {
-    isPull,
     mySocketId,
     initWs,
     roomLiving,
@@ -50,7 +44,6 @@ export function usePull(roomId: string) {
     damuList,
     handleSendGetLiveUser,
   } = useWebsocket();
-  isPull.value = true;
   const { flvVideoEl, flvIsPlaying, startFlvPlay, destroyFlv } = useFlvPlay();
   const { hlsVideoEl, hlsIsPlaying, startHlsPlay, destroyHls } = useHlsPlay();
   const stopDrawingArr = ref<any[]>([]);
@@ -68,17 +61,6 @@ export function usePull(roomId: string) {
     remoteVideo.value = [];
   }
 
-  watch(
-    () => appStore.pkStream,
-    (newval) => {
-      console.log('pkStream变了', newval);
-      stopDrawingArr.value = [];
-      stopDrawingArr.value.forEach((cb) => cb());
-      if (videoWrapRef.value) {
-      }
-    }
-  );
-
   watch(hlsVideoEl, () => {
     stopDrawingArr.value = [];
     stopDrawingArr.value.forEach((cb) => cb());
@@ -125,7 +107,6 @@ export function usePull(roomId: string) {
           videoHeight.value = `${w}x${h}`;
         },
       });
-      console.log(canvas, 2221211223);
       stopDrawingArr.value.push(stopDrawing);
       remoteVideo.value.push(canvas);
       videoLoading.value = false;
@@ -198,12 +179,15 @@ export function usePull(roomId: string) {
             LiveRoomTypeEnum.msr,
             LiveRoomTypeEnum.srs,
             LiveRoomTypeEnum.obs,
-            LiveRoomTypeEnum.pk,
             LiveRoomTypeEnum.tencent_css,
             LiveRoomTypeEnum.tencent_css_pk,
           ].includes(liveRoomInfo.type!)
         ) {
           handlePlay(liveRoomInfo!);
+        } else if (LiveRoomTypeEnum.pk === liveRoomInfo.type!) {
+          if (!route.query.pkKey) {
+            handlePlay(liveRoomInfo!);
+          }
         }
       } else {
         closeRtc();
@@ -283,6 +267,7 @@ export function usePull(roomId: string) {
       isPlaying.value = newVal;
     }
   );
+
   watch(
     () => flvIsPlaying.value,
     (newVal) => {
@@ -290,21 +275,6 @@ export function usePull(roomId: string) {
     }
   );
 
-  watch(
-    () => networkStore.rtcMap,
-    (newVal) => {
-      if (appStore.liveRoomInfo?.type === LiveRoomTypeEnum.wertc_live) {
-        newVal.forEach((item) => {
-          videoLoading.value = false;
-        });
-      }
-    },
-    {
-      deep: true,
-      immediate: true,
-    }
-  );
-
   watch(
     () => localStream.value,
     (val) => {
@@ -364,19 +334,6 @@ export function usePull(roomId: string) {
     { deep: true }
   );
 
-  watch(
-    [
-      () => userStore.userInfo,
-      () => networkStore.wsMap.get(roomId)?.socketIo?.connected,
-    ],
-    ([userInfo, connected]) => {
-      if (userInfo && connected) {
-        const instance = networkStore.wsMap.get(roomId);
-        if (!instance) return;
-      }
-    }
-  );
-
   function initPull(autolay = true) {
     autoplayVal.value = autolay;
     if (autoplayVal.value) {
@@ -400,10 +357,6 @@ export function usePull(roomId: string) {
     });
   }
 
-  function addVideo() {
-    sidebarList.value.push({ socketId: mySocketId.value });
-  }
-
   function keydownDanmu(event: KeyboardEvent) {
     const key = event.key.toLowerCase();
     if (key === 'enter') {
@@ -453,7 +406,6 @@ export function usePull(roomId: string) {
     closeRtc,
     keydownDanmu,
     sendDanmu,
-    addVideo,
     handleSendGetLiveUser,
     danmuMsgType,
     isPlaying,
@@ -466,7 +418,6 @@ export function usePull(roomId: string) {
     videoLoading,
     damuList,
     liveUserList,
-    sidebarList,
     danmuStr,
     anchorInfo,
   };

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

@@ -7,7 +7,6 @@ import {
   fetchUserHasLiveRoom,
 } from '@/api/userLiveRoom';
 import { DanmuMsgTypeEnum, WsMessageMsgIsFileEnum } from '@/interface';
-import { handleMaxFramerate } from '@/network/webRTC';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { useUserStore } from '@/store/user';
@@ -19,6 +18,7 @@ import {
   WsRoomNoLiveType,
 } from '@/types/websocket';
 import { createVideo, generateBase64 } from '@/utils';
+import { handleMaxFramerate } from '@/utils/network/webRTC';
 
 import { commentAuthTip, loginTip } from './use-login';
 import { useTip } from './use-tip';
@@ -41,7 +41,6 @@ export function usePush() {
 
   const {
     roomLiving,
-    isPull,
     initWs,
     handleStartLive,
     handleSendGetLiveUser,
@@ -55,8 +54,6 @@ export function usePush() {
     currentResolutionRatio,
   } = useWebsocket();
 
-  isPull.value = false;
-
   onMounted(() => {
     if (!loginTip()) return;
   });
@@ -90,7 +87,6 @@ export function usePush() {
       });
       console.log('新的allTrack音频轨', mixedStream.getAudioTracks());
       console.log('新的allTrack视频轨', mixedStream.getVideoTracks());
-      // localStream.value = mixedStream;
     },
     { deep: true }
   );

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

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

+ 1 - 1
src/hooks/use-tip.ts

@@ -1,6 +1,6 @@
 import { ComponentPublicInstance, VNode, createApp } from 'vue';
 
-import ModalCpt from './modal/index.vue';
+import ModalCpt from '@/hooks/tipModal/index.vue';
 
 const app = createApp(ModalCpt);
 const container = document.createElement('div');

+ 15 - 53
src/hooks/use-websocket.ts

@@ -15,8 +15,6 @@ import {
   ILiveUser,
   WsMessageMsgIsFileEnum,
 } from '@/interface';
-import { WebRTCClass } from '@/network/webRTC';
-import { WebSocketClass, prettierReceiveWsMsg } from '@/network/webSocket';
 import router, { routerName } from '@/router';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
@@ -44,6 +42,10 @@ import {
   WsUpdateJoinInfoType,
 } from '@/types/websocket';
 import { createNullVideo, handleUserMedia } from '@/utils';
+import {
+  WebSocketClass,
+  prettierReceiveWsMsg,
+} from '@/utils/network/webSocket';
 
 import { useWebRtcMeetingPk } from './webrtc/meetingPk';
 
@@ -65,10 +67,8 @@ export const useWebsocket = () => {
   const loopGetLiveUserTimer = ref();
   const liveUserList = ref<ILiveUser[]>([]);
   const roomId = ref('');
-  const isPull = ref(false);
   const roomLiving = ref(false);
   const isAnchor = ref(false);
-  const isSRS = ref(false);
   const anchorInfo = ref<IUser>();
   const anchorSocketId = ref('');
   const canvasVideoStream = ref<MediaStream>();
@@ -151,6 +151,9 @@ export const useWebsocket = () => {
     msrDelay: number;
     msrMaxDelay: number;
   }) {
+    if (appStore.liveRoomInfo) {
+      appStore.liveRoomInfo.type = type;
+    }
     networkStore.wsMap.get(roomId.value)?.send<WsStartLiveType['data']>({
       requestId: getRandomString(8),
       msgType: WsMsgTypeEnum.startLive,
@@ -268,57 +271,13 @@ export const useWebsocket = () => {
     });
 
     // 收到srsOffer
-    ws.socketIo.on(
-      WsMsgTypeEnum.srsOffer,
-      async (data: WsOfferType['data']) => {
-        console.log('收到srsOffer', data);
-        if (data.receiver === mySocketId.value) {
-          console.warn('是发给我的srsOffer');
-          const videoEl = createNullVideo();
-          const rtc = new WebRTCClass({
-            maxBitrate: currentMaxBitrate.value,
-            maxFramerate: currentMaxFramerate.value,
-            resolutionRatio: currentResolutionRatio.value,
-            roomId: roomId.value,
-            videoEl,
-            isSRS: true,
-            sender: data.sender,
-            receiver: data.receiver,
-          });
-          isSRS.value = true;
-          await rtc.setRemoteDescription(data.sdp);
-          const answerSdp = await rtc.createAnswer();
-          if (answerSdp) {
-            await rtc.setLocalDescription(answerSdp);
-            ws.send<WsAnswerType['data']>({
-              requestId: getRandomString(8),
-              msgType: WsMsgTypeEnum.srsAnswer,
-              data: {
-                live_room_id: Number(roomId.value),
-                sdp: answerSdp,
-                receiver: data.sender,
-                sender: mySocketId.value,
-              },
-            });
-          } else {
-            console.error('srsOffer的answerSdp为空');
-          }
-        } else {
-          console.error('不是发给我的srsOffer');
-        }
-      }
-    );
+    ws.socketIo.on(WsMsgTypeEnum.srsOffer, (data: WsOfferType['data']) => {
+      console.log('收到srsOffer', data);
+    });
 
     // 收到srsAnswer
     ws.socketIo.on(WsMsgTypeEnum.srsAnswer, (data: WsAnswerType['data']) => {
       console.log('收到srsAnswer', data);
-      if (data.receiver === mySocketId.value) {
-        console.warn('是发给我的srsAnswer');
-        const rtc = networkStore.rtcMap.get(data.sender);
-        rtc?.setRemoteDescription(data.sdp);
-      } else {
-        console.error('不是发给我的srsAnswer');
-      }
     });
 
     // 收到srsCandidate
@@ -379,7 +338,11 @@ export const useWebsocket = () => {
                 sdp: data.sdp,
               });
             } else {
-              window.$message.error('验证pkKey错误!');
+              await useTip({
+                content: '加入PK失败,验证pkKey错误!',
+                hiddenCancel: true,
+                hiddenClose: true,
+              });
             }
           } else {
             console.error('不是发给我的nativeWebRtcOffer');
@@ -748,7 +711,6 @@ export const useWebsocket = () => {
   }
 
   return {
-    isPull,
     initWs,
     handleStartLive,
     handleSendGetLiveUser,

+ 1 - 1
src/hooks/webrtc/live.ts

@@ -2,10 +2,10 @@ import { getRandomString } from 'billd-utils';
 import { ref } from 'vue';
 
 import { useRTCParams } from '@/hooks/use-rtcParams';
-import { WebRTCClass } from '@/network/webRTC';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { WsAnswerType, WsMsgTypeEnum, WsOfferType } from '@/types/websocket';
+import { WebRTCClass } from '@/utils/network/webRTC';
 
 export const useWebRtcLive = () => {
   const appStore = useAppStore();

+ 1 - 1
src/hooks/webrtc/meetingOne.ts

@@ -2,10 +2,10 @@ import { getRandomString } from 'billd-utils';
 import { ref } from 'vue';
 
 import { useRTCParams } from '@/hooks/use-rtcParams';
-import { WebRTCClass } from '@/network/webRTC';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { WsAnswerType, WsMsgTypeEnum, WsOfferType } from '@/types/websocket';
+import { WebRTCClass } from '@/utils/network/webRTC';
 
 export const useWebRtcMeetingOne = () => {
   const appStore = useAppStore();

+ 1 - 1
src/hooks/webrtc/meetingPk.ts

@@ -2,10 +2,10 @@ import { getRandomString } from 'billd-utils';
 import { ref } from 'vue';
 
 import { useRTCParams } from '@/hooks/use-rtcParams';
-import { WebRTCClass } from '@/network/webRTC';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { WsAnswerType, WsMsgTypeEnum, WsOfferType } from '@/types/websocket';
+import { WebRTCClass } from '@/utils/network/webRTC';
 
 export const useWebRtcMeetingPk = () => {
   const appStore = useAppStore();

+ 1 - 1
src/hooks/webrtc/meetingTwo.ts

@@ -2,10 +2,10 @@ import { getRandomString } from 'billd-utils';
 import { ref } from 'vue';
 
 import { useRTCParams } from '@/hooks/use-rtcParams';
-import { WebRTCClass } from '@/network/webRTC';
 import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { WsAnswerType, WsMsgTypeEnum, WsOfferType } from '@/types/websocket';
+import { WebRTCClass } from '@/utils/network/webRTC';
 
 export const useWebRtcManyToManyMeeting = () => {
   const appStore = useAppStore();

+ 1 - 3
src/hooks/webrtc/srs.ts

@@ -4,15 +4,13 @@ import { ref } from 'vue';
 import { fetchRtcV1Publish } from '@/api/srs';
 import { SRS_CB_URL_PARAMS } from '@/constant';
 import { useRTCParams } from '@/hooks/use-rtcParams';
-import { WebRTCClass } from '@/network/webRTC';
-import { useAppStore } from '@/store/app';
 import { useNetworkStore } from '@/store/network';
 import { useUserStore } from '@/store/user';
 import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
+import { WebRTCClass } from '@/utils/network/webRTC';
 
 export const useWebRtcSrs = () => {
   const userStore = useUserStore();
-  const appStore = useAppStore();
   const networkStore = useNetworkStore();
 
   const { maxBitrate, maxFramerate, resolutionRatio } = useRTCParams();

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

@@ -283,7 +283,14 @@
               <a class="item">
                 <div class="txt">{{ t('layout.tencentCssPkLive') }}</div>
               </a>
-              <div class="tip"><div class="tip-txt">有什么区别?</div></div>
+              <div class="tip">
+                <div
+                  class="tip-txt"
+                  @click="handleWebsiteJump"
+                >
+                  有什么区别?
+                </div>
+              </div>
             </div>
           </template>
         </Dropdown>
@@ -516,6 +523,13 @@ function handleStartLive(key: LiveRoomTypeEnum) {
   });
   openToTarget(url.href);
 }
+
+function handleWebsiteJump() {
+  const url = router.resolve({
+    name: routerName.pushStreamDifferent,
+  });
+  openToTarget(url.href);
+}
 </script>
 
 <style lang="scss" scoped>

+ 11 - 4
src/router/index.ts

@@ -38,6 +38,7 @@ export const routerName = {
   team: 'team',
   oauth: 'oauth',
   release: 'release',
+  pushStreamDifferent: 'pushStreamDifferent',
   notFound: 'notFound',
   group: 'group',
   profile: 'profile',
@@ -71,22 +72,28 @@ export const defaultRoutes: RouteRecordRaw[] = [
           {
             name: routerName.group,
             path: 'group',
-            component: () => import('@/views/group/index.vue'),
+            component: () => import('@/views/about/group/index.vue'),
           },
           {
             name: routerName.faq,
             path: 'faq',
-            component: () => import('@/views/faq/index.vue'),
+            component: () => import('@/views/about/faq/index.vue'),
           },
           {
             name: routerName.team,
             path: 'team',
-            component: () => import('@/views/team/index.vue'),
+            component: () => import('@/views/about/team/index.vue'),
           },
           {
             name: routerName.release,
             path: 'release',
-            component: () => import('@/views/release/index.vue'),
+            component: () => import('@/views/about/release/index.vue'),
+          },
+          {
+            name: routerName.pushStreamDifferent,
+            path: 'pushStreamDifferent',
+            component: () =>
+              import('@/views/about/pushStreamDifferent/index.vue'),
           },
         ],
       },

+ 0 - 1
src/store/app/index.ts

@@ -41,7 +41,6 @@ export type AppRootState = {
   liveRoomInfo?: ILiveRoom;
   showLoginModal: boolean;
   disableSpeaking: Map<number, { exp: number; label: string }>;
-  pkStream?: MediaStream;
   showSigninRedDot: boolean;
 };
 

+ 2 - 2
src/store/network/index.ts

@@ -1,7 +1,7 @@
 import { defineStore } from 'pinia';
 
-import { WebRTCClass } from '@/network/webRTC';
-import { WebSocketClass } from '@/network/webSocket';
+import { WebRTCClass } from '@/utils/network/webRTC';
+import { WebSocketClass } from '@/utils/network/webSocket';
 
 type NetworkRootState = {
   wsMap: Map<string, WebSocketClass>;

+ 4 - 4
src/utils/index.ts

@@ -216,9 +216,9 @@ export function saveFile(data: { file: File; fileName: string }) {
       resolve({ code: 2 });
       return;
     }
-    function onError(err) {
+    function onError(error) {
       console.error('saveFile错误', data.fileName);
-      console.log(err);
+      console.log(error);
       resolve({ code: 2 });
     }
     function onFs(fs) {
@@ -266,9 +266,9 @@ export function readFile(fileName: string) {
       resolve({ code: 2 });
       return;
     }
-    function onError(err) {
+    function onError(error) {
       console.error('readFile错误', fileName);
-      console.log(err);
+      console.log(error);
       resolve({ code: 2 });
     }
     function onFs(fs) {

+ 0 - 0
src/network/webRTC.ts → src/utils/network/webRTC.ts


+ 0 - 0
src/network/webSocket.ts → src/utils/network/webSocket.ts


+ 2 - 0
src/views/faq/index.vue → src/views/about/faq/index.vue

@@ -159,6 +159,8 @@ import { AUTHOR_GITHUB, COMMON_URL } from '@/constant';
   }
   .aside {
     padding-left: 90px;
+    width: 150px;
+
     .title {
       color: rgb(33, 53, 71);
       font-weight: 700;

+ 0 - 0
src/views/group/index.vue → src/views/about/group/index.vue


+ 128 - 0
src/views/about/pushStreamDifferent/index.vue

@@ -0,0 +1,128 @@
+<template>
+  <div class="release-wrap">
+    <div class="content">
+      <h1 class="title">不同开播的区别</h1>
+      <div class="hr"></div>
+      <div class="list">
+        <div class="item">
+          <h2>SRS直播</h2>
+          <p>
+            推流到服务器,由服务器的SRS进行转发(RTMP、FLV、HLS、WebRTC等)。
+          </p>
+          <p>优点:不同客户端都能拉流;缺点:对服务器带宽要求高。</p>
+        </div>
+        <div class="hr"></div>
+        <div class="item">
+          <h2>WebRTC直播</h2>
+          <p>原生WebRTC一对多。</p>
+          <p>优点:延迟低。缺点:对客户端上传带宽要求高。</p>
+        </div>
+        <div class="hr"></div>
+        <div class="item">
+          <h2>WebRTC会议</h2>
+          <p>原生WebRTC多对多。</p>
+          <p>优点:延迟低。缺点:对客户端上传带宽要求高。</p>
+        </div>
+        <div class="hr"></div>
+        <div class="item">
+          <h2>Msr直播</h2>
+          <p>
+            类似bilibili的web直播间实现,浏览器录制直播画面,并上传到服务器进行推流。
+          </p>
+          <p>
+            优点:兼容性对比webRTC好;缺点:延迟高,且对网络要求严格,并且也需要后端和音视频相关部门的支持。
+          </p>
+        </div>
+        <div class="hr"></div>
+        <div class="item">
+          <h2>打PK直播</h2>
+          <p>
+            不同主播之间进行直播互动,然后由任意一个主播将所有画面进行混流,推送到服务器的SRS进行转发,让观众能看到这个直播互动。
+          </p>
+          <p>此方式是webRTC直播和SRS直播的混合,优缺点也继承自它们。</p>
+        </div>
+        <div class="hr"></div>
+        <div class="item">
+          <h2>腾讯云直播</h2>
+          <p>
+            推流到腾讯云云直播,由腾讯云进行转发(RTMP、FLV、HLS、WebRTC等)。
+          </p>
+          <p>优点:腾讯云云直播自带CDN;缺点:收费。</p>
+        </div>
+        <div class="item">
+          <h2>腾讯云打PK</h2>
+          <p>在打PK直播的基础上,将SRS替换成腾讯云云直播。</p>
+          <p>优点:腾讯云云直播自带CDN;缺点:收费。</p>
+        </div>
+      </div>
+    </div>
+    <div class="aside">
+      <div class="title">本页目录</div>
+      <div class="item">SRS直播</div>
+      <div class="item">WebRTC直播</div>
+      <div class="item">WebRTC会议</div>
+      <div class="item">Msr直播</div>
+      <div class="item">打PK直播</div>
+      <div class="item">腾讯云直播</div>
+      <div class="item">腾讯云打PK</div>
+    </div>
+  </div>
+</template>
+
+<script lang="ts" setup></script>
+
+<style lang="scss" scoped>
+.release-wrap {
+  display: flex;
+  box-sizing: border-box;
+  margin: 0 auto;
+  padding-top: 50px;
+  width: 960px;
+  color: rgb(33, 53, 71);
+
+  .content {
+    flex: 1;
+    .title {
+      margin: 0;
+      font-weight: 500;
+      font-size: 40px;
+      margin-bottom: 20px;
+    }
+    .hr {
+      margin: 60px 0 20px 0;
+      width: 100%;
+      height: 1px;
+      background-color: #e7e7e7;
+    }
+    .list {
+      h2 {
+        font-weight: 600;
+      }
+      .item {
+        position: relative;
+        font-size: 16px;
+      }
+    }
+  }
+
+  .aside {
+    padding-left: 90px;
+    width: 150px;
+    .title {
+      color: rgb(33, 53, 71);
+      font-weight: 700;
+      font-size: 12px;
+      margin-bottom: 8px;
+    }
+    .item {
+      margin-bottom: 8px;
+      color: rgba(60, 60, 60, 0.7);
+      font-size: 13px;
+      cursor: pointer;
+      &:hover {
+        color: #213547;
+      }
+    }
+  }
+}
+</style>

+ 2 - 0
src/views/release/index.vue → src/views/about/release/index.vue

@@ -96,6 +96,8 @@ onMounted(() => {
 
   .aside {
     padding-left: 90px;
+    width: 150px;
+
     .title {
       color: rgb(33, 53, 71);
       font-weight: 700;

+ 0 - 0
src/views/team/index.vue → src/views/about/team/index.vue


+ 2 - 0
src/views/privatizationDeployment/index.vue

@@ -134,6 +134,8 @@ import { openToTarget } from 'billd-utils';
   }
   .aside {
     padding-left: 90px;
+    width: 150px;
+
     .title {
       margin-bottom: 8px;
       color: rgb(33, 53, 71);

+ 1 - 1
src/views/profile/index.vue

@@ -40,7 +40,7 @@ import { onMounted, ref } from 'vue';
 import { useRoute } from 'vue-router';
 
 import { fetchFindUser } from '@/api/user';
-import { IUser } from '@/interface';
+import { IUser } from '@/types/IUser';
 import { getLiveRoomPageUrl } from '@/utils';
 
 const loading = ref(false);

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

@@ -608,7 +608,6 @@ async function handlePk() {
       console.log('onnegotiationneeded', event);
     };
     stream?.getTracks().forEach((track) => {
-      console.log(rtc, stream, track);
       rtc.peerConnection?.addTrack(track, stream);
     });
   }

+ 0 - 1
src/views/pull/recharge/index.vue

@@ -91,7 +91,6 @@ async function startPay() {
   const res = await fetchFindByTypeGoods(GoodsTypeEnum.recharge);
   if (res.code === 200) {
     showQrPay.value = false;
-    console.log('dddd', money.value);
     nextTick(() => {
       goodsInfo.money = money.value * 100;
       goodsInfo.goodsId = res.data.id!;

+ 2 - 29
src/views/push/index.vue

@@ -529,39 +529,13 @@ watch(
   }
 );
 
-watch(
-  () => appStore.pkStream,
-  (newval) => {
-    console.log('pkStream', newval);
-    if (newval) {
-      addMediaOk({
-        id: getRandomEnglishString(6),
-        openEye: true,
-        audio: 2,
-        video: 1,
-        mediaName: 'pkStream',
-        type: MediaTypeEnum.pk,
-        track: newval.getVideoTracks()[0],
-        trackid: newval.getVideoTracks()[0].id,
-        stream: newval,
-        streamid: newval.id,
-        hidden: false,
-        muted: false,
-        scaleInfo: {},
-      });
-    }
-  }
-);
-
 watch(
   () => networkStore.rtcMap,
   (newVal) => {
-    console.log('rtcMap变了');
     newVal.forEach((item) => {
       if (appStore.allTrack.find((v) => v.mediaName === item.receiver)) {
         return;
       }
-      console.log('addMediaOkaddMediaOk', item.receiver);
       addMediaOk({
         id: getRandomEnglishString(6),
         openEye: true,
@@ -663,7 +637,7 @@ async function uploadChange() {
   }
 }
 
-function handleAllType() {
+function handleMediaRecorderAllType() {
   const types = [
     'video/webm',
     'audio/webm',
@@ -746,6 +720,7 @@ onMounted(() => {
   setTimeout(() => {
     scrollTo(0, 0);
   }, 100);
+  handleMediaRecorderAllType();
   initUserMedia();
   initCanvas();
   handleCache();
@@ -2082,12 +2057,10 @@ function editMediaOk(val: AppRootState['allTrack'][0]) {
         }
       }
       if (val.openEye) {
-        console.log('显示的');
         if (item.canvasDom) {
           item.canvasDom.opacity = 1;
         }
       } else {
-        console.log('bu显示的');
         if (item.canvasDom) {
           item.canvasDom.opacity = 0;
         }

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

@@ -127,7 +127,6 @@ function startPay(item: IGoods) {
   }
   showQrPay.value = false;
   nextTick(() => {
-    console.log(item.price, '333');
     goodsInfo.money = item.price!;
     goodsInfo.goodsId = item.id!;
     showQrPay.value = true;

+ 2 - 0
src/views/sponsors/index.vue

@@ -252,6 +252,8 @@ const silverList = ref([
   }
   .aside {
     padding-left: 90px;
+    width: 150px;
+
     .title {
       margin-bottom: 8px;
       color: rgb(33, 53, 71);