Răsfoiți Sursa

fix: 优化

shuisheng 2 ani în urmă
părinte
comite
78e7628ed5

+ 5 - 1
README.md

@@ -42,8 +42,11 @@ billd 直播间,目前实现了类似 [bilibili 的 Web 在线直播](https://
 - [x] 原生 webrtc 推拉流
 - [x] srs webrtc 推流,`http-flv` 或 `hls`拉流
 - [x] msr 推流,ffmpeg转码,`http-flv` 或 `hls`拉流
+- [x] 一对一打PK
+- [ ] 一对多打PK
 - [x] 前端混流
 - [x] 推流鉴权
+- [x] 拉流鉴权
 - [x] [OBS](https://github.com/obsproject/obs-studio)、[FFmpeg](https://ffmpeg.org)推流
 - [x] 用户模块(qq 登录)
 - [x] 支付模块(支付宝当面付)
@@ -51,7 +54,8 @@ billd 直播间,目前实现了类似 [bilibili 的 Web 在线直播](https://
 - [x] 商品模块
 - [x] 适配移动端
 - [x] 在线后台
-- [x] 接入腾讯云直播
+- [x] 接入腾讯云-云直播
+- [ ] 接入腾讯云-实时音视频TRTC
 
 ## 技术栈
 

+ 1 - 1
src/App.vue

@@ -1,6 +1,6 @@
 <template>
   <n-config-provider :theme-overrides="themeOverrides">
-    <router-view></router-view>
+    <n-dialog-provider><router-view></router-view></n-dialog-provider>
   </n-config-provider>
 </template>
 

+ 5 - 0
src/api/liveRoom.ts

@@ -8,6 +8,11 @@ export function fetchLiveRoomList(params) {
   });
 }
 
+export function fetchVerifyPkKey(data: { liveRoomId: number; key }) {
+  return request.get(`/live_room/verify_pk_key/${data.liveRoomId}`, {
+    params: { key: data.key },
+  });
+}
 export function fetchUpdateLiveRoomKey() {
   return request.instance({
     url: '/live_room/update_key',

+ 36 - 38
src/hooks/use-websocket.ts

@@ -2,6 +2,7 @@ import { copyToClipBoard, getRandomString } from 'billd-utils';
 import { NButton, useDialog } from 'naive-ui';
 import { computed, h, onUnmounted, ref, watch } from 'vue';
 
+import { fetchVerifyPkKey } from '@/api/liveRoom';
 import { fetchRtcV1Publish } from '@/api/srs';
 import { SRS_CB_URL_PARAMS, THEME_COLOR, WEBSOCKET_URL } from '@/constant';
 import {
@@ -37,11 +38,13 @@ import {
   WsStartLiveType,
 } from '@/types/websocket';
 import { createVideo } from '@/utils';
+import { useRoute } from 'vue-router';
 
 import { useRTCParams } from './use-rtcParams';
 import { useTip } from './use-tip';
 
 export const useWebsocket = () => {
+  const route = useRoute();
   const appStore = useAppStore();
   const userStore = useUserStore();
   const networkStore = useNetworkStore();
@@ -73,8 +76,8 @@ export const useWebsocket = () => {
   watch(
     () => appStore.pkStream,
     (newval) => {
-      console.log('转推到srs', newval);
       if (newval && isAnchor.value) {
+        console.log('转推到srs', newval);
         srsWebRtc.sendOffer({
           isPk: true,
           sender: mySocketId.value,
@@ -148,9 +151,7 @@ export const useWebsocket = () => {
       msgType: WsMsgTypeEnum.join,
       data: {
         socket_id: mySocketId.value,
-        live_room: {
-          id: Number(roomId.value),
-        },
+        live_room_id: Number(roomId.value),
         user_info: userStore.userInfo,
       },
     });
@@ -371,12 +372,10 @@ export const useWebsocket = () => {
           api: `/rtc/v1/publish/`,
           clientip: null,
           sdp: offerSdp!.sdp!,
-          // eslint-disable-next-line
           streamurl: `${myLiveRoom.rtmp_url!}?${
             SRS_CB_URL_PARAMS.publishKey
-            // eslint-disable-next-line
           }=${myLiveRoom.key!}&${SRS_CB_URL_PARAMS.publishType}=${
-            LiveRoomTypeEnum.user_srs
+            isPk ? LiveRoomTypeEnum.user_pk : LiveRoomTypeEnum.user_srs
           }`,
           tid: getRandomString(10),
         });
@@ -530,35 +529,42 @@ export const useWebsocket = () => {
       WsMsgTypeEnum.nativeWebRtcOffer,
       async (data: WsOfferType['data']) => {
         console.log('收到nativeWebRtcOffer', data);
-        console.log(data.live_room.type, LiveRoomTypeEnum.user_pk);
         if (data.live_room.type === LiveRoomTypeEnum.user_pk) {
           if (!isAnchor.value) {
-            dialog.warning({
-              title: '提示',
-              content: '是否加入PK',
-              positiveText: '确认',
-              onPositiveClick() {
-                return new Promise((resolve) => {
-                  resolve(1);
-                  if (data.receiver === mySocketId.value) {
-                    console.warn('是发给我的nativeWebRtcOffer');
-                    nativeWebRtc.sendAnswer({
-                      isPk: data.live_room.type === LiveRoomTypeEnum.user_pk,
-                      sender: data.sender,
-                      receiver: data.receiver,
-                      sdp: data.sdp,
-                    });
-                  } else {
-                    console.error('不是发给我的nativeWebRtcOffer');
-                  }
-                });
-              },
+            const res = await fetchVerifyPkKey({
+              liveRoomId: Number(roomId.value),
+              key: route.query.pkKey,
             });
+            if (res.code === 200 && res.data === true) {
+              dialog.warning({
+                title: '提示',
+                content: '是否加入PK',
+                positiveText: '确认',
+                onPositiveClick() {
+                  return new Promise((resolve) => {
+                    resolve(1);
+                    if (data.receiver === mySocketId.value) {
+                      console.warn('是发给我的nativeWebRtcOffer');
+                      nativeWebRtc.sendAnswer({
+                        isPk: true,
+                        sender: data.sender,
+                        receiver: data.receiver,
+                        sdp: data.sdp,
+                      });
+                    } else {
+                      console.error('不是发给我的nativeWebRtcOffer');
+                    }
+                  });
+                },
+              });
+            } else {
+              window.$message.error('验证pkKey错误!');
+            }
           } else {
             if (data.receiver === mySocketId.value) {
               console.warn('是发给我的nativeWebRtcOffer');
               nativeWebRtc.sendAnswer({
-                isPk: data.live_room.type === LiveRoomTypeEnum.user_pk,
+                isPk: true,
                 sender: data.sender,
                 receiver: data.receiver,
                 sdp: data.sdp,
@@ -727,17 +733,13 @@ export const useWebsocket = () => {
     // 用户加入房间完成
     ws.socketIo.on(WsMsgTypeEnum.joined, (data: WsJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.joined, data);
-      // liveUserList.value.push({
-      //   id: data.socket_id,
-      //   userInfo: data.user_info,
-      // });
       appStore.setLiveRoomInfo(data.live_room);
       anchorInfo.value = data.anchor_info;
       ws.send<WsGetLiveUserType['data']>({
         requestId: getRandomString(8),
         msgType: WsMsgTypeEnum.getLiveUser,
         data: {
-          live_room_id: data.live_room.id!,
+          live_room_id: data.live_room_id,
         },
       });
     });
@@ -745,10 +747,6 @@ export const useWebsocket = () => {
     // 其他用户加入房间
     ws.socketIo.on(WsMsgTypeEnum.otherJoin, (data: WsOtherJoinType['data']) => {
       prettierReceiveWsMsg(WsMsgTypeEnum.otherJoin, data);
-      // liveUserList.value.push({
-      //   id: data.join_socket_id,
-      //   userInfo: data.join_user_info,
-      // });
       const requestId = getRandomString(8);
       const danmu: IDanmu = {
         live_room_id: data.live_room.id!,

+ 10 - 12
src/layout/pc/index.vue

@@ -1,16 +1,14 @@
 <template>
-  <n-dialog-provider>
-    <div class="layout">
-      <div class="fixed-mask"></div>
-      <HeadCpt></HeadCpt>
-      <router-view v-slot="{ Component }">
-        <component :is="Component"></component>
-      </router-view>
-      <ModalCpt></ModalCpt>
-      <SidebarCpt v-if="MODULE_CONFIG_SWITCH.sidebar"></SidebarCpt>
-      <LoginModal v-if="appStore.showLoginModal"></LoginModal>
-    </div>
-  </n-dialog-provider>
+  <div class="layout">
+    <div class="fixed-mask"></div>
+    <HeadCpt></HeadCpt>
+    <router-view v-slot="{ Component }">
+      <component :is="Component"></component>
+    </router-view>
+    <ModalCpt></ModalCpt>
+    <SidebarCpt v-if="MODULE_CONFIG_SWITCH.sidebar"></SidebarCpt>
+    <LoginModal v-if="appStore.showLoginModal"></LoginModal>
+  </div>
 </template>
 
 <script lang="ts" setup>

+ 2 - 1
src/types/websocket.ts

@@ -185,7 +185,8 @@ export type WsStartLiveType = IWsFormat<{
 /** 用户加入直播间 */
 export type WsJoinType = IWsFormat<{
   socket_id: string;
-  live_room: ILiveRoom;
+  live_room_id: number;
+  live_room?: ILiveRoom;
   anchor_info?: IUser;
   user_info?: IUser;
 }>;

+ 1 - 3
src/views/h5/index.vue

@@ -79,16 +79,14 @@ import { onMounted, onUnmounted, ref } from 'vue';
 
 import { fetchAreaLiveRoomList } from '@/api/area';
 import { IArea, IAreaLiveRoom } from '@/interface';
-
 import router, { mobileRouterName, routerName } from '@/router';
+import { useAppStore } from '@/store/app';
 import {
   LiveRoomIsShowEnum,
   LiveRoomPullIsShouldAuthEnum,
   LiveRoomUseCDNEnum,
 } from '@/types/ILiveRoom';
 
-import { useAppStore } from '@/store/app';
-
 const appStore = useAppStore();
 const liveRoomList = ref<IArea[]>([]);
 

+ 2 - 3
src/views/push/selectMediaModal/index.vue

@@ -4,6 +4,7 @@
       title="选择直播素材"
       :mask-closable="false"
       @close="emits('close')"
+      width="'350px'"
     >
       <n-space justify="center">
         <n-button
@@ -44,9 +45,7 @@ onMounted(() => {});
 <style lang="scss" scoped>
 .select-media-wrap {
   text-align: initial;
-  :deep(.container) {
-    width: 350px;
-  }
+
   .container {
     padding-top: 10px;
   }