shuisheng hai 1 ano
pai
achega
01460bc8d4

+ 11 - 0
README.md

@@ -16,6 +16,17 @@
   基于Vue3 + WebRTC + Node + SRS + FFmpeg搭建的直播间
 </p>
 
+<div align="center">
+
+![stars](https://img.shields.io/github/stars/galaxy-s10/billd-live)
+![forks](https://img.shields.io/github/forks/galaxy-s10/billd-live)
+
+![version](https://img.shields.io/github/package-json/v/galaxy-s10/billd-live)
+![License](https://img.shields.io/github/license/galaxy-s10/billd-live)
+![language](https://img.shields.io/github/languages/top/galaxy-s10/billd-live)
+
+</div>
+
 ## 简介
 
 billd 直播间,目前实现了类似 [bilibili 的 Web 在线直播](https://live.bilibili.com)功能,即你(房主)可以发布直播,别人进入你的直播间后能看到你的直播内容;而你也可以作为观众,进入别人的直播间看别人的直播内容。

+ 4 - 3
package.json

@@ -17,6 +17,7 @@
     "lint": "eslint --config ./.eslintrc.js . --ext .js,.jsx,.ts,.tsx,.vue --cache",
     "lint:fix": "eslint --config ./.eslintrc.js . --ext .js,.jsx,.ts,.tsx,.vue --cache --fix",
     "oxclint": "pnpm dlx oxlint@latest",
+    "oxlint": "oxlint",
     "prepare": "husky install",
     "prettier": "prettier --write .",
     "release": "standard-version",
@@ -40,10 +41,10 @@
     "@vueuse/core": "^10.11.1",
     "@webav/av-recorder": "^0.3.3",
     "axios": "^1.2.1",
-    "billd-deploy": "^1.0.25",
+    "billd-deploy": "^1.0.26",
     "billd-html-webpack-plugin": "^1.0.6",
     "billd-scss": "^0.0.8",
-    "billd-utils": "^0.0.22",
+    "billd-utils": "^0.0.25",
     "cos-js-sdk-v5": "^1.8.6",
     "fabric": "^5.3.0",
     "flv.js": "^1.6.2",
@@ -108,7 +109,7 @@
     "lint-staged": "^12.1.4",
     "mini-css-extract-plugin": "^2.6.0",
     "node-emoji": "^1.11.0",
-    "oxlint": "^0.9.9",
+    "oxlint": "^0.13.0",
     "portfinder": "^1.0.28",
     "postcss": "^8.4.8",
     "postcss-loader": "^6.2.1",

+ 48 - 56
pnpm-lock.yaml

@@ -21,8 +21,8 @@ importers:
         specifier: ^1.2.1
         version: 1.3.4
       billd-deploy:
-        specifier: ^1.0.25
-        version: 1.0.25(@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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2))
+        specifier: ^1.0.26
+        version: 1.0.26(@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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2))
       billd-html-webpack-plugin:
         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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2))
@@ -30,8 +30,8 @@ importers:
         specifier: ^0.0.8
         version: 0.0.8
       billd-utils:
-        specifier: ^0.0.22
-        version: 0.0.22(tslib@2.6.1)(typescript@5.1.6)
+        specifier: ^0.0.25
+        version: 0.0.25(tslib@2.6.1)(typescript@5.1.6)
       cos-js-sdk-v5:
         specifier: ^1.8.6
         version: 1.8.6
@@ -220,8 +220,8 @@ importers:
         specifier: ^1.11.0
         version: 1.11.0
       oxlint:
-        specifier: ^0.9.9
-        version: 0.9.9
+        specifier: ^0.13.0
+        version: 0.13.0
       portfinder:
         specifier: ^1.0.28
         version: 1.0.32
@@ -1589,47 +1589,47 @@ packages:
     resolution: {integrity: sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==}
     engines: {node: '>= 8'}
 
-  '@oxlint/darwin-arm64@0.9.9':
-    resolution: {integrity: sha512-My2KfUByjRl49p0rr/Glx9Y/hjney1uFk0JXNjwHqYToHqO9fY/IZ6XT1fdw9sX+1hdpq9bmj88rnkpvu0/cRw==}
+  '@oxlint/darwin-arm64@0.13.0':
+    resolution: {integrity: sha512-TFVi4gWKmn4oUoaS6AUU6cvlA+xLCIHQWA27LdnyfmRDerxHSWaG4yPNq9bvhDAeeEWqid5+TR5ndu4WRhEr5A==}
     cpu: [arm64]
     os: [darwin]
 
-  '@oxlint/darwin-x64@0.9.9':
-    resolution: {integrity: sha512-k0r0t+MAzrk8yWs0nxyD9Skfb+Ozmu6HRMTJIsUTLV4AKMt9CZBlLVS0OXzXHi72AOHz3UUve5rXxevVVY9lHQ==}
+  '@oxlint/darwin-x64@0.13.0':
+    resolution: {integrity: sha512-ihbegvRXcED2Bgz9Lt4AGFoNfvh/tUZPrFR5DZ3Hn8muab+PEFfXXXKcelSDpTB4za5bDXz6dZcAUUfQUWPwxg==}
     cpu: [x64]
     os: [darwin]
 
-  '@oxlint/linux-arm64-gnu@0.9.9':
-    resolution: {integrity: sha512-atiotr1pN3rr0i7Ww3SpOEOvkFex97S8GwYmiTlSng0kp+FSIZD6Kjlr9k3oayf9RZUDRuAE4WptwV1KYLvIDw==}
+  '@oxlint/linux-arm64-gnu@0.13.0':
+    resolution: {integrity: sha512-k4r03/29d+IdcT30B6H5TpWT7bFrkqbRrFQ5VS6GX5ISN0yRdagu4Q08sDimCTTXvg5H9Z/sHmxbw7tbjGGW4w==}
     cpu: [arm64]
     os: [linux]
     libc: [glibc]
 
-  '@oxlint/linux-arm64-musl@0.9.9':
-    resolution: {integrity: sha512-vmd6Eog6WiudMTT0Fa8u5N+47caaWF2KVUHOSEV/d/WauVx+ZOR9z1LEM+54AZwn3Z2TbtFOJDiz7iDukZPbfw==}
+  '@oxlint/linux-arm64-musl@0.13.0':
+    resolution: {integrity: sha512-m+LFHCwNydIrGHDz1VPTaQsZewaqYadKhzyjsw4TRf0g5fxeEC4tkv6MI80D2S//QO6DJi8VcnPfVqGWoS5vQQ==}
     cpu: [arm64]
     os: [linux]
     libc: [musl]
 
-  '@oxlint/linux-x64-gnu@0.9.9':
-    resolution: {integrity: sha512-AUmSRerK4VXIMcTYYk25KGoOU2/z+NGItUhI6nJgMFktrbF8MUD6hlf3vaQZNle454z7FDJNSjARM0bB+xpBiQ==}
+  '@oxlint/linux-x64-gnu@0.13.0':
+    resolution: {integrity: sha512-Kixb9MXi5muDKsrNo5k7TANEE3DuUUSKIgoBN68LbX4n2owjCsq/gnzVjQ/rDK0vFn0JQMxMXWjBZvV64ybXMQ==}
     cpu: [x64]
     os: [linux]
     libc: [glibc]
 
-  '@oxlint/linux-x64-musl@0.9.9':
-    resolution: {integrity: sha512-jQYIx5KUYbpXbXBFPgIwRPLSm3AO5wa+32BQYASIOCPcsPywV+HJKbQpzmWqXDYel6hrifmIxspgxHhGMlHJ1Q==}
+  '@oxlint/linux-x64-musl@0.13.0':
+    resolution: {integrity: sha512-wCCsesDf05G0bjXMrxAvH36Cl4q0oavR3fo4N5NJyyrRdZ+feAZSsfaHRpvlqkJyUM3vhP6emKrXzIN5fp22dw==}
     cpu: [x64]
     os: [linux]
     libc: [musl]
 
-  '@oxlint/win32-arm64@0.9.9':
-    resolution: {integrity: sha512-HSOztIKmiivfUAoxGx4qyerYV+aAXGvKbwWf8j4RorAEg2WWBdhVe9XHoSdqgYsOBi1515+YXxXiSRX3F/0xAg==}
+  '@oxlint/win32-arm64@0.13.0':
+    resolution: {integrity: sha512-xO6oZ+0yjYuEviKqRUVWMuYvzYqJDHd0IcBss8J2o45OS9SH+mNNk5gZJm9uKbDdmFZcDn2OlZxAiygVMxHt9g==}
     cpu: [arm64]
     os: [win32]
 
-  '@oxlint/win32-x64@0.9.9':
-    resolution: {integrity: sha512-T1/tNxqoYd/MMqi1dhSVzAVL0ZINvXDBEQWm6OCSrrjRM6c9UQydTzsgLWfvm9uHWngcMuRGXhN3F+D6KEYs3w==}
+  '@oxlint/win32-x64@0.13.0':
+    resolution: {integrity: sha512-NiiaQ/AD1ILQ8cXRxdjE/dRMCRABFbelSYqoFrrklV2Y7hwtF0Law48GvM5ysQbz/NHVpQpnVNQOQ3cevywn3w==}
     cpu: [x64]
     os: [win32]
 
@@ -2498,8 +2498,8 @@ packages:
   big.js@5.2.2:
     resolution: {integrity: sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==}
 
-  billd-deploy@1.0.25:
-    resolution: {integrity: sha512-gy9p3SvbZxCJIRPBkaO/Kb/BiH4wO7mkl/F34aJ2qZLvzuiFkJg5T7kkTujDcjPoDQxmuYR3eHuSJHdgZADxCg==}
+  billd-deploy@1.0.26:
+    resolution: {integrity: sha512-NoBKnWA5dbzI5fgK42GXcul7WfatzIirlWhY0w0SwKx1i7dWn5LvgKk0y3jIR3z9uXG1uVVLcVPW05jp1/rmeQ==}
 
   billd-html-webpack-plugin@1.0.6:
     resolution: {integrity: sha512-zM294oAMqRD1rlqoyC1E9QbFsBgMPYStODmQKwUjI+xd02Rwo+3iZhmlQ8q0EuF2KnyhwDwhxyZfDGSo6Ow8Tw==}
@@ -2507,8 +2507,8 @@ packages:
   billd-scss@0.0.8:
     resolution: {integrity: sha512-42gyDYnmRICjqrzk3qbqVygpvjpMu/2rMk41x8HyWLOf457EkXyCiAAFrFR2XM3/c6PHWbtD+IhP8MHUV6JeyA==}
 
-  billd-utils@0.0.22:
-    resolution: {integrity: sha512-koOfFzbzSkw6gMYyOKNMzAJHYMhUWHr3swPW48rT7PwZMvBkAtH93bHEVuDCwariWrSwxCGIqozOzp5YaeePqQ==}
+  billd-utils@0.0.25:
+    resolution: {integrity: sha512-Pp8ivF15L93ZG0vA1hqAqaDwzxesKYam6tEO0DcDjKHGVR6ylVl/ASsHlniR5hbvp4XFhBiKJ0oMwJvab9GFiQ==}
 
   binary-extensions@2.2.0:
     resolution: {integrity: sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==}
@@ -3798,10 +3798,6 @@ packages:
     resolution: {integrity: sha512-B9/wizE4WngqQftFPmdaMYlXoJlJOYxGQOanC77fq9k8+Z0v5dDSVh+3glErdIROP//s/jgb7ZuxKfB8nVyo0g==}
     hasBin: true
 
-  fast-xml-parser@4.3.4:
-    resolution: {integrity: sha512-utnwm92SyozgA3hhH2I8qldf2lBqm6qHOICawRNRFu1qMe3+oqr+GcXjGqTmXTMGE5T4eC03kr/rlh5C1IRdZA==}
-    hasBin: true
-
   fast-xml-parser@4.5.0:
     resolution: {integrity: sha512-/PlTQCI96+fZMAOLMZK4CWG1ItCbfZ/0jx7UIJFChPNrx7tcEgerUgWbeieCM9MfHInUDyK8DWYZ+YrywDJuTg==}
     hasBin: true
@@ -5271,8 +5267,8 @@ packages:
     engines: {node: '>=0.10.0'}
     hasBin: true
 
-  oxlint@0.9.9:
-    resolution: {integrity: sha512-EqUmSKgnU7KNCi29uFe5MQnUZ0GH569Inkry/e84k4lwVRv1QuDr4DHLpu0cXBN2atwhKf1Szk/3uxmB2qgPbw==}
+  oxlint@0.13.0:
+    resolution: {integrity: sha512-YUwybs9U5siS54Q+vVkxMQXiNF6LHeLRxihj6toUFwrYSxL1wsV6HUiAS8Vig+USDIGoEDdGBgpq29iwWDjYHw==}
     engines: {node: '>=14.*'}
     hasBin: true
 
@@ -8949,28 +8945,28 @@ snapshots:
       '@nodelib/fs.scandir': 2.1.5
       fastq: 1.15.0
 
-  '@oxlint/darwin-arm64@0.9.9':
+  '@oxlint/darwin-arm64@0.13.0':
     optional: true
 
-  '@oxlint/darwin-x64@0.9.9':
+  '@oxlint/darwin-x64@0.13.0':
     optional: true
 
-  '@oxlint/linux-arm64-gnu@0.9.9':
+  '@oxlint/linux-arm64-gnu@0.13.0':
     optional: true
 
-  '@oxlint/linux-arm64-musl@0.9.9':
+  '@oxlint/linux-arm64-musl@0.13.0':
     optional: true
 
-  '@oxlint/linux-x64-gnu@0.9.9':
+  '@oxlint/linux-x64-gnu@0.13.0':
     optional: true
 
-  '@oxlint/linux-x64-musl@0.9.9':
+  '@oxlint/linux-x64-musl@0.13.0':
     optional: true
 
-  '@oxlint/win32-arm64@0.9.9':
+  '@oxlint/win32-arm64@0.13.0':
     optional: true
 
-  '@oxlint/win32-x64@0.9.9':
+  '@oxlint/win32-x64@0.13.0':
     optional: true
 
   '@pkgr/utils@2.4.2':
@@ -9955,7 +9951,7 @@ snapshots:
 
   big.js@5.2.2: {}
 
-  billd-deploy@1.0.25(@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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2)):
+  billd-deploy@1.0.26(@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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2)):
     dependencies:
       ali-oss: 6.20.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(webpack-bundle-analyzer@4.8.0)(webpack-dev-server@4.13.1)(webpack@5.76.2))
@@ -9997,7 +9993,7 @@ snapshots:
 
   billd-scss@0.0.8: {}
 
-  billd-utils@0.0.22(tslib@2.6.1)(typescript@5.1.6):
+  billd-utils@0.0.25(tslib@2.6.1)(typescript@5.1.6):
     dependencies:
       '@babel/core': 7.21.3
       '@babel/plugin-transform-runtime': 7.21.0(@babel/core@7.21.3)
@@ -11236,7 +11232,7 @@ snapshots:
 
   esdk-obs-nodejs@3.23.11:
     dependencies:
-      fast-xml-parser: 4.3.4
+      fast-xml-parser: 4.5.0
       log4js: 6.9.1
     transitivePeerDependencies:
       - supports-color
@@ -11563,10 +11559,6 @@ snapshots:
     dependencies:
       strnum: 1.0.5
 
-  fast-xml-parser@4.3.4:
-    dependencies:
-      strnum: 1.0.5
-
   fast-xml-parser@4.5.0:
     dependencies:
       strnum: 1.0.5
@@ -13142,16 +13134,16 @@ snapshots:
     dependencies:
       minimist: 1.2.8
 
-  oxlint@0.9.9:
+  oxlint@0.13.0:
     optionalDependencies:
-      '@oxlint/darwin-arm64': 0.9.9
-      '@oxlint/darwin-x64': 0.9.9
-      '@oxlint/linux-arm64-gnu': 0.9.9
-      '@oxlint/linux-arm64-musl': 0.9.9
-      '@oxlint/linux-x64-gnu': 0.9.9
-      '@oxlint/linux-x64-musl': 0.9.9
-      '@oxlint/win32-arm64': 0.9.9
-      '@oxlint/win32-x64': 0.9.9
+      '@oxlint/darwin-arm64': 0.13.0
+      '@oxlint/darwin-x64': 0.13.0
+      '@oxlint/linux-arm64-gnu': 0.13.0
+      '@oxlint/linux-arm64-musl': 0.13.0
+      '@oxlint/linux-x64-gnu': 0.13.0
+      '@oxlint/linux-x64-musl': 0.13.0
+      '@oxlint/win32-arm64': 0.13.0
+      '@oxlint/win32-x64': 0.13.0
 
   p-finally@2.0.1: {}
 

+ 0 - 23
src/App.vue

@@ -22,7 +22,6 @@ import { GlobalThemeOverrides, NConfigProvider } from 'naive-ui';
 import { onMounted, ref, watch } from 'vue';
 import { useRoute } from 'vue-router';
 
-import { fetchSettingsList } from '@/api/settings';
 import { THEME_COLOR, appBuildInfo } from '@/constant';
 import { useCheckUpdate } from '@/hooks/use-common';
 import { useGoogleAd } from '@/hooks/use-google-ad';
@@ -111,27 +110,6 @@ async function handleGlobalMsgMyList() {
   }
 }
 
-function initSettings() {
-  setTimeout(async () => {
-    if (route.path !== '/') {
-      return;
-    }
-    const res = await fetchSettingsList({});
-    if (res.code === 200) {
-      const allowHomeModal = res.data.rows.find(
-        (v) => v.key === 'allow_home_modal'
-      );
-      const homeModalContent = res.data.rows.find(
-        (v) => v.key === 'home_modal_content'
-      );
-      if (allowHomeModal?.value === '1' && homeModalContent?.value) {
-        showModal.value = true;
-        modalContent.value = homeModalContent.value;
-      }
-    }
-  }, 500);
-}
-
 async function getAreaList() {
   const res = await fetchAreaList({ orderName: 'priority', orderBy: 'desc' });
   if (res.code === 200) {
@@ -141,7 +119,6 @@ async function getAreaList() {
 
 function initGlobalData() {
   getAreaList();
-  initSettings();
 }
 
 function handleUpdate() {

+ 0 - 33
src/api/liveConfig.ts

@@ -1,33 +0,0 @@
-import { ILiveConfig } from '@/interface';
-import request from '@/utils/request';
-
-export function fetchFrontendList(params) {
-  return request.get('/live_config/list', { params });
-}
-
-export function fetchFindFrontend(id: number) {
-  return request.get(`/live_config/find/${id}`);
-}
-
-export function fetchFindLiveConfigByKey(key: string) {
-  return request.get(`/live_config/find_by_key/${key}`);
-}
-
-export function fetchCreateFrontend(data: ILiveConfig) {
-  return request.post(`/live_config/create`, data);
-}
-
-export function fetchUpdateFrontend(data: ILiveConfig) {
-  return request.instance({
-    url: `/live_config/update/${data.id!}`,
-    method: 'put',
-    data,
-  });
-}
-
-export function fetchDeleteFrontend(id: number) {
-  return request.instance({
-    url: `/live_config/delete/${id}`,
-    method: 'delete',
-  });
-}

+ 0 - 6
src/api/settings.ts

@@ -1,6 +0,0 @@
-import { IList, IPaging, ISettings } from '@/interface';
-import request from '@/utils/request';
-
-export function fetchSettingsList(params: IList<ISettings>) {
-  return request.get<IPaging<ISettings>>('/settings/list', { params });
-}

+ 3 - 0
src/constant.ts

@@ -35,7 +35,10 @@ export const SRS_CB_URL_QUERY = {
   userToken: 'usertoken',
   userId: 'userid',
   randomId: 'randomid',
+  roomId: 'roomid',
+  isdev: 'isdev',
 };
+
 export const URL_QUERY = {
   goodsType: 'goodsType',
   pkKey: 'pkKey',

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

@@ -470,7 +470,6 @@ export function usePull() {
           }
         }
       }
-      console.log('kkkkk', val, liveRoomInfo?.type);
       if (!roomLiving.value) {
         closeRtc();
         handleStopDrawing();
@@ -553,6 +552,7 @@ export function usePull() {
     if (key === 'enter') {
       event.preventDefault();
       sendDanmuTxt(danmuStr.value);
+      danmuStr.value = '';
     }
   }
 

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

@@ -280,6 +280,7 @@ export function usePush() {
     if (key === 'enter') {
       event.preventDefault();
       sendDanmuTxt(danmuStr.value);
+      danmuStr.value = '';
     }
   }
 

+ 13 - 25
src/hooks/use-websocket.ts

@@ -31,14 +31,12 @@ import { useUserStore } from '@/store/user';
 import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
 import { IUser } from '@/types/IUser';
 import {
-  WSGetRoomAllUserType,
   WSLivePkKeyType,
   WsAnswerType,
   WsBatchSendOffer,
   WsCandidateType,
   WsConnectStatusEnum,
   WsDisableSpeakingType,
-  WsHeartbeatType,
   WsJoinType,
   WsLeavedType,
   WsMessageType,
@@ -103,6 +101,7 @@ export const useWebsocket = () => {
   const currentAudioContentHint = ref(audioContentHint.value[0].value);
   const timerObj = ref({});
   const damuList = ref<IWsMessage[]>([]);
+  const joinedDelay = 5000;
 
   onUnmounted(() => {
     clearInterval(loopHeartbeatTimer.value);
@@ -220,19 +219,7 @@ export const useWebsocket = () => {
     });
   }
 
-  function handleHeartbeat() {
-    loopHeartbeatTimer.value = setInterval(() => {
-      const ws = networkStore.wsMap.get(roomId.value);
-      if (!ws) return;
-      ws.send<WsHeartbeatType['data']>({
-        requestId: getRandomString(8),
-        msgType: WsMsgTypeEnum.heartbeat,
-        data: {
-          live_room_id: Number(roomId.value),
-        },
-      });
-    }, 1000 * 5);
-  }
+  function handleHeartbeat() {}
 
   function handleStartLive({
     name,
@@ -387,8 +374,8 @@ export const useWebsocket = () => {
       requestId: getRandomString(8),
       msgType: WsMsgTypeEnum.join,
       data: {
-        isBilibili: isBilibili.value,
         live_room_id: Number(roomId.value),
+        duration: joinedDelay / 1000,
       },
     });
   }
@@ -582,15 +569,6 @@ export const useWebsocket = () => {
       roomLiving.value = false;
     });
 
-    // 当前所有在线用户
-    ws.socketIo.on(
-      WsMsgTypeEnum.liveUser,
-      (data: WSGetRoomAllUserType['data']) => {
-        prettierReceiveWsMsg(WsMsgTypeEnum.liveUser, data);
-        liveUserList.value = data.liveUser;
-      }
-    );
-
     // 收到用户发送消息
     ws.socketIo.on(WsMsgTypeEnum.message, (data: WsMessageType) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.message, data);
@@ -709,6 +687,16 @@ export const useWebsocket = () => {
     // 用户加入房间完成
     ws.socketIo.on(WsMsgTypeEnum.joined, async (data: WsJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.joined, data);
+      setInterval(() => {
+        networkStore.wsMap.get(roomId.value)?.send<WsJoinType['data']>({
+          requestId: getRandomString(8),
+          msgType: WsMsgTypeEnum.keepJoined,
+          data: {
+            live_room_id: Number(roomId.value),
+            duration: joinedDelay / 1000,
+          },
+        });
+      }, joinedDelay);
       if (route.name === routerName.pull || route.name === routerName.h5Room) {
         // 当前是拉流页面
         if (

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

@@ -91,7 +91,7 @@ export const useForwardAll = () => {
               SRS_CB_URL_QUERY.publishKey
             }=${myLiveRoom.key!}&${SRS_CB_URL_QUERY.publishType}=${
               isPk.value ? LiveRoomTypeEnum.pk : LiveRoomTypeEnum.forward_all
-            }`,
+            }&${SRS_CB_URL_QUERY.userId}=${userStore.userInfo?.id!}`,
           });
           if (answerRes.data.code !== 0) {
             console.error('/rtc/v1/publish/拿不到sdp');

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

@@ -97,7 +97,7 @@ export const useForwardBilibili = () => {
               isPk.value
                 ? LiveRoomTypeEnum.pk
                 : LiveRoomTypeEnum.forward_bilibili
-            }`,
+            }&${SRS_CB_URL_QUERY.userId}=${userStore.userInfo?.id!}`,
           });
           if (answerRes.data.code !== 0) {
             console.error('/rtc/v1/publish/拿不到sdp');

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

@@ -91,7 +91,7 @@ export const useForwardHuya = () => {
               SRS_CB_URL_QUERY.publishKey
             }=${myLiveRoom.key!}&${SRS_CB_URL_QUERY.publishType}=${
               isPk.value ? LiveRoomTypeEnum.pk : LiveRoomTypeEnum.forward_huya
-            }`,
+            }&${SRS_CB_URL_QUERY.userId}=${userStore.userInfo?.id!}`,
           });
           if (answerRes.data.code !== 0) {
             console.error('/rtc/v1/publish/拿不到sdp');

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

@@ -96,7 +96,7 @@ export const useWebRtcSrs = () => {
               SRS_CB_URL_QUERY.publishKey
             }=${myLiveRoom.key!}&${SRS_CB_URL_QUERY.publishType}=${
               isPk.value ? LiveRoomTypeEnum.pk : LiveRoomTypeEnum.srs
-            }`,
+            }&${SRS_CB_URL_QUERY.userId}=${userStore.userInfo?.id!}`,
           });
           if (answerRes.data.code !== 0) {
             console.error('/rtc/v1/publish/拿不到sdp');

+ 7 - 18
src/interface.ts

@@ -481,17 +481,6 @@ export enum FormTypeEnum {
   'datePicker' = 'datePicker',
 }
 
-export interface ILiveConfig {
-  id?: number;
-  key?: string;
-  value?: string;
-  desc?: string;
-  type?: FormTypeEnum;
-  created_at?: string;
-  updated_at?: string;
-  deleted_at?: string;
-}
-
 export enum WalletRecordEnum {
   reward,
   recharge,
@@ -749,14 +738,14 @@ export enum DanmuMsgTypeEnum {
 }
 
 export interface ILiveUser {
-  // id: string;
-  // rooms?: string[];
-  // userInfo?: IUser;
-  created_at: string;
+  created_at: number;
+  client_ip: string;
   value: {
-    socketId: string;
-    joinRoomId: number;
-    userInfo?: IUser;
+    live_room_id: number;
+    live_room_name: string;
+    user_id: number;
+    user_username: string;
+    user_avatar: string;
   };
 }
 

+ 1 - 1
src/spec-config.ts

@@ -39,7 +39,7 @@ export const QINIU_KODO = {
   },
   'hss-backup': {
     domain: `backup.${prodDomain}`,
-    url: `http://backup.${prodDomain}/`,
+    url: `http://backup.${prodDomain}`,
     bucket: 'hss-backup',
     prefix: {
       'billd-live/mysql/': 'billd-live/mysql/',

+ 4 - 8
src/types/websocket.ts

@@ -1,4 +1,4 @@
-import { ILiveUser, IWsMessage } from '@/interface';
+import { IWsMessage } from '@/interface';
 import { ILiveRoom, LiveRoomTypeEnum } from '@/types/ILiveRoom';
 import { IUser } from '@/types/IUser';
 
@@ -26,6 +26,8 @@ export enum WsMsgTypeEnum {
   join = 'join',
   /** 用户进入聊天完成 */
   joined = 'joined',
+  /** 用户进入聊天完成 */
+  keepJoined = 'keepJoined',
   /** 用户进入聊天 */
   otherJoin = 'otherJoin',
   /** 用户退出聊天 */
@@ -116,11 +118,6 @@ export type WSLivePkKeyType = IWsFormat<{
   key: string;
 }>;
 
-/** 获取在线用户 */
-export type WSGetRoomAllUserType = IWsFormat<{
-  liveUser: ILiveUser[];
-}>;
-
 /** 获取在线用户 */
 export type WsGetLiveUserType = IWsFormat<{
   live_room_id: number;
@@ -215,9 +212,8 @@ export type WsStartLiveType = IWsFormat<{
 export type WsJoinType = IWsFormat<{
   live_room_id: number;
   live_room?: ILiveRoom;
-  anchor_info?: IUser;
-  isBilibili?: boolean;
   socket_list?: string[];
+  duration: number;
 }>;
 
 /** 用户离开直播间 */

+ 21 - 35
src/views/h5/room/index.vue

@@ -167,25 +167,13 @@
               :key="index"
               class="item"
             >
-              <div
-                class="info"
-                v-if="item.value?.userInfo"
-              >
+              <div class="info">
                 <div
                   class="avatar"
-                  v-lazy:background-image="item.value.userInfo.avatar"
+                  v-lazy:background-image="item.value.user_avatar"
                 ></div>
                 <div class="username">
-                  {{ item.value.userInfo.username }}
-                </div>
-              </div>
-              <div
-                class="info"
-                v-else
-              >
-                <div class="avatar"></div>
-                <div class="username">
-                  {{ item.value?.socketId }}
+                  {{ item.value.user_username }}
                 </div>
               </div>
             </div>
@@ -300,7 +288,6 @@ import router, { mobileRouterName } from '@/router';
 import { useAppStore } from '@/store/app';
 import { useCacheStore } from '@/store/cache';
 import { useUserStore } from '@/store/user';
-import { LiveRoomTypeEnum } from '@/types/ILiveRoom';
 import { IUser } from '@/types/IUser';
 import { formatTimeHour } from '@/utils';
 
@@ -321,6 +308,7 @@ const roomId = ref(route.params.roomId as string);
 const loopGetLiveUserTimer = ref();
 
 const {
+  initRtcReceive,
   videoWrapRef,
   handlePlay,
   initPull,
@@ -330,7 +318,6 @@ const {
   closeWs,
   liveUserList,
   showPlayBtn,
-  autoplayVal,
   videoLoading,
   damuList,
   danmuStr,
@@ -347,16 +334,16 @@ onUnmounted(() => {
   clearInterval(loopGetLiveUserTimer.value);
 });
 
-onMounted(() => {
+onMounted(async () => {
+  setTimeout(() => {
+    scrollTo(0, 0);
+  }, 100);
   if (!Number(roomId.value)) {
     return;
   }
   initPull({ roomId: roomId.value, autolay: true });
   showPlayBtn.value = true;
   videoWrapRef.value = remoteVideoRef.value;
-  setTimeout(() => {
-    scrollTo(0, 0);
-  }, 100);
   videoWrapHeight.value =
     document.documentElement.clientWidth / appStore.videoRatio;
   nextTick(() => {
@@ -367,9 +354,15 @@ onMounted(() => {
       containerHeight.value = res;
     }
   });
-  getLiveRoomInfo();
+  await handleFindLiveRoomInfo();
   handleSendGetLiveUser(Number(roomId.value));
   handleHistoryMsg();
+  initWs({
+    roomId: roomId.value,
+    isBilibili: false,
+    isAnchor: false,
+  });
+  initRtcReceive();
 });
 
 function handleSendDanmu() {
@@ -419,13 +412,16 @@ async function handleHistoryMsg() {
 }
 
 function handleSendGetLiveUser(liveRoomId: number) {
+  clearInterval(loopGetLiveUserTimer.value);
   async function main() {
     const res = await fetchLiveRoomOnlineUser({ live_room_id: liveRoomId });
     if (res.code === 200) {
       liveUserList.value = res.data;
     }
   }
-  main();
+  setTimeout(() => {
+    main();
+  }, 500);
   loopGetLiveUserTimer.value = setInterval(() => {
     main();
   }, 1000 * 3);
@@ -475,9 +471,8 @@ function handleFullScreen() {
   }
 }
 
-async function getLiveRoomInfo() {
+async function handleFindLiveRoomInfo() {
   try {
-    videoLoading.value = true;
     const res = await fetchFindLiveRoom(Number(roomId.value));
     if (res.code === 200) {
       if (res.data) {
@@ -488,19 +483,10 @@ async function getLiveRoomInfo() {
         } else {
           videoLoading.value = false;
         }
-        if (res.data?.type === LiveRoomTypeEnum.wertc_live) {
-          autoplayVal.value = true;
-          showPlayBtn.value = false;
-        } else {
-          showPlayBtn.value = true;
-        }
-        initWs({ roomId: roomId.value, isAnchor: false });
       }
     }
   } catch (error) {
-    console.error(error);
-  } finally {
-    videoLoading.value = false;
+    console.log(error);
   }
 }
 

+ 4 - 22
src/views/home/index.vue

@@ -54,7 +54,7 @@
           >
             <div class="txt">CDN</div>
           </div>
-          <div class="billd-logo">Billd直播</div>
+          <div class="logo-watermark">Billd直播</div>
           <div
             class="cover"
             :style="{
@@ -291,7 +291,6 @@ import { useRouter } from 'vue-router';
 
 import { fetchLiveBilibiliGetUserRecommend } from '@/api/bilibili';
 import { fetchLiveList } from '@/api/live';
-import { fetchFindLiveConfigByKey } from '@/api/liveConfig';
 import { sliderList, URL_QUERY } from '@/constant';
 import { usePull } from '@/hooks/use-pull';
 import { ILive, LiveLineEnum } from '@/interface';
@@ -361,7 +360,6 @@ onMounted(() => {
   intersectionObserver.observe(loadMoreRef.value!);
   handleSlideList();
   getLiveRoomList();
-  getBg();
   videoWrapRef.value = videoWrapTmpRef.value;
 });
 
@@ -420,23 +418,6 @@ function handleSlideList() {
   interactionList.value = res;
 }
 
-async function getBg() {
-  try {
-    const res = await fetchFindLiveConfigByKey('frontend_live_home_bg');
-    if (res.code === 200) {
-      const reg = /.+\.mp4$/g;
-      const url = res.data.value as string;
-      if (reg.exec(url)) {
-        configVideo.value = res.data.value;
-      } else {
-        configBg.value = res.data.value;
-      }
-    }
-  } catch (error) {
-    console.log(error);
-  }
-}
-
 function handleRefresh() {
   playLive(appStore.liveRoomInfo!);
 }
@@ -574,12 +555,13 @@ function joinRoom(data) {
             font-size: 14px;
           }
         }
-        .billd-logo {
+        .logo-watermark {
           position: absolute;
           top: 10px;
           left: 10px;
           z-index: 2;
-          color: rgba($color: #fff, $alpha: 0.4);
+          line-height: 1;
+          color: rgba($color: #fff, $alpha: 0.5);
           font-weight: bold;
           font-size: 30px;
         }

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

@@ -501,7 +501,7 @@ async function handleUpdateKey() {
       userStore.userInfo.live_rooms[0].push_webrtc_url =
         res.data.srsPushRes.push_webrtc_url;
       userStore.userInfo.live_rooms[0].cdn_push_obs_server =
-        res.data.srsPushRes.push_obs_server;
+        res.data.cdnPushRes.push_obs_server;
       userStore.userInfo.live_rooms[0].cdn_push_obs_stream_key =
         res.data.cdnPushRes.push_obs_stream_key;
       userStore.userInfo.live_rooms[0].cdn_push_rtmp_url =

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

@@ -235,28 +235,13 @@
             :key="index"
             class="item"
           >
-            <div
-              class="info"
-              v-if="item.value?.userInfo"
-              @click="jumpProfile(item.value.userInfo.id!)"
-            >
+            <div class="info">
               <div
                 class="avatar"
-                :style="{
-                  backgroundImage: `url(${item.value?.userInfo?.avatar})`,
-                }"
+                v-lazy:background-image="item.value.user_avatar"
               ></div>
               <div class="username">
-                {{ item.value.userInfo.username }}
-              </div>
-            </div>
-            <div
-              class="info"
-              v-else
-            >
-              <div class="avatar"></div>
-              <div class="username">
-                {{ item.value?.socketId }}
+                {{ item.value.user_username }}
               </div>
             </div>
           </div>
@@ -580,6 +565,9 @@ const rtcBytesReceived = computed(() => {
 });
 
 onMounted(async () => {
+  setTimeout(() => {
+    scrollTo(0, 0);
+  }, 100);
   roomId.value = route.params.roomId as string;
   initPull({ roomId: roomId.value, autolay: true });
   if (route.query[URL_QUERY.isBilibili] === '1') {
@@ -602,9 +590,7 @@ onMounted(async () => {
   appStore.videoControls.speed = true;
 
   videoWrapRef.value = remoteVideoRef.value;
-  setTimeout(() => {
-    scrollTo(0, 0);
-  }, 100);
+
   handleHistoryMsg();
   getGoodsList();
   if (topRef.value && bottomRef.value && remoteVideoRef.value) {
@@ -688,13 +674,16 @@ async function handleBilibil() {
 }
 
 function handleSendGetLiveUser(liveRoomId: number) {
+  clearInterval(loopGetLiveUserTimer.value);
   async function main() {
     const res = await fetchLiveRoomOnlineUser({ live_room_id: liveRoomId });
     if (res.code === 200) {
       liveUserList.value = res.data;
     }
   }
-  main();
+  setTimeout(() => {
+    main();
+  }, 500);
   loopGetLiveUserTimer.value = setInterval(() => {
     main();
   }, 1000 * 3);
@@ -1361,7 +1350,7 @@ function handleScrollTop() {
             align-items: center;
             cursor: pointer;
             .avatar {
-              margin-right: 5px;
+              margin-right: 10px;
               width: 25px;
               height: 25px;
               border-radius: 50%;

+ 5 - 23
src/views/push/index.vue

@@ -773,19 +773,6 @@ watch(
   }
 );
 
-watch(
-  () => route.query[URL_QUERY.roomId],
-  (newval) => {
-    if (newval) {
-      handleSendGetLiveUser(Number(newval));
-    }
-  },
-  {
-    deep: true,
-    immediate: true,
-  }
-);
-
 function roomNameIsOk() {
   if (!appStore.liveRoomInfo) return;
   if (!appStore.liveRoomInfo.name!.length) {
@@ -967,15 +954,6 @@ function handleMsr(stream: MediaStream) {
   });
 }
 
-watch(
-  () => roomId.value,
-  (newval) => {
-    if (newval) {
-      handleHistoryMsg();
-    }
-  }
-);
-
 watch(
   () => appStore.areaList,
   (newval) => {
@@ -997,6 +975,8 @@ watch(
   () => appStore.liveRoomInfo,
   (newval) => {
     if (newval) {
+      handleSendGetLiveUser(appStore.liveRoomInfo?.id!);
+      handleHistoryMsg();
       const area = newval.areas?.[0];
       if (area) {
         currentArea.value = area.id!;
@@ -1049,7 +1029,9 @@ function handleSendGetLiveUser(liveRoomId: number) {
       liveUserList.value = res.data;
     }
   }
-  main();
+  setTimeout(() => {
+    main();
+  }, 500);
   loopGetLiveUserTimer.value = setInterval(() => {
     main();
   }, 1000 * 3);