shuisheng 3 gadi atpakaļ
vecāks
revīzija
ed73af90d3

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

@@ -105,6 +105,7 @@ export function useHlsPlay() {
   }
 
   function setMuted(val) {
+    console.log('setMuted', val);
     if (hlsVideoEl.value) {
       hlsVideoEl.value.muted = val;
     }

+ 6 - 4
src/hooks/use-pull.ts

@@ -145,7 +145,7 @@ export function usePull({
           stream.value?.getVideoTracks().forEach((track) => {
             console.log('视频轨enabled:', track.id, track.enabled);
             const video = createVideo({});
-            video.id = track.id;
+            video.setAttribute('track-id', track.id);
             video.srcObject = new MediaStream([track]);
             canvasRef.value?.appendChild(video);
             videoElArr.value.push(video);
@@ -153,7 +153,7 @@ export function usePull({
           stream.value?.getAudioTracks().forEach((track) => {
             console.log('音频轨enabled:', track.id, track.enabled);
             const video = createVideo({});
-            video.id = track.id;
+            video.setAttribute('track-id', track.id);
             video.srcObject = new MediaStream([track]);
             canvasRef.value?.appendChild(video);
             videoElArr.value.push(video);
@@ -166,15 +166,17 @@ export function usePull({
           stream.value?.getVideoTracks().forEach((track) => {
             console.log('视频轨enabled:', track.id, track.enabled);
             const video = createVideo({});
-            video.id = track.id;
+            video.setAttribute('track-id', track.id);
             video.srcObject = new MediaStream([track]);
+            // document.body.appendChild(video);
+            // console.log('kkkk', video);
             canvasRef.value?.appendChild(video);
             videoElArr.value.push(video);
           });
           stream.value?.getAudioTracks().forEach((track) => {
             console.log('音频轨enabled:', track.id, track.enabled);
             const video = createVideo({});
-            video.id = track.id;
+            video.setAttribute('track-id', track.id);
             video.srcObject = new MediaStream([track]);
             canvasRef.value?.appendChild(video);
             videoElArr.value.push(video);

+ 10 - 13
src/hooks/use-push.ts

@@ -80,35 +80,30 @@ export function usePush({
   } = useWs();
 
   watch(
-    () => localStream,
+    () => localStream.value,
     (stream) => {
       console.log('localStream变了');
-      console.log('音频轨:', stream.value?.getAudioTracks());
-      console.log('视频轨:', stream.value?.getVideoTracks());
+      console.log('音频轨:', stream?.getAudioTracks());
+      console.log('视频轨:', stream?.getVideoTracks());
       videoElArr.value.forEach((dom) => {
         dom.remove();
       });
-      stream.value?.getVideoTracks().forEach((track) => {
+      stream?.getVideoTracks().forEach((track) => {
         console.log('视频轨enabled:', track.id, track.enabled);
         const video = createVideo({});
-        video.id = track.id;
+        video.setAttribute('track-id', track.id);
         video.srcObject = new MediaStream([track]);
         localVideoRef.value?.appendChild(video);
         videoElArr.value.push(video);
       });
-      stream.value?.getAudioTracks().forEach((track) => {
+      stream?.getAudioTracks().forEach((track) => {
         console.log('音频轨enabled:', track.id, track.enabled);
         const video = createVideo({});
-        video.id = track.id;
+        video.setAttribute('track-id', track.id);
         video.srcObject = new MediaStream([track]);
         localVideoRef.value?.appendChild(video);
         videoElArr.value.push(video);
       });
-      // if (stream.value) {
-      //   localVideoRef.value!.srcObject = stream.value;
-      // } else {
-      //   localVideoRef.value!.srcObject = null;
-      // }
     },
     { deep: true }
   );
@@ -207,7 +202,9 @@ export function usePush({
       }
     });
     if (el) {
-      const res1 = videoElArr.value.find((item) => item.id === el.track.id);
+      const res1 = videoElArr.value.find(
+        (item) => item.getAttribute('track-id') === el.track.id
+      );
       if (res1) {
         lastCoverImg.value = handleCoverImg(res1);
       }

+ 84 - 41
src/hooks/use-ws.ts

@@ -51,6 +51,18 @@ export const useWs = () => {
   const localStream = ref<MediaStream>();
   const lastCoverImg = ref('');
   const maxBitrate = ref([
+    {
+      label: '1',
+      value: 1,
+    },
+    {
+      label: '10',
+      value: 10,
+    },
+    {
+      label: '50',
+      value: 50,
+    },
     {
       label: '1000',
       value: 1000,
@@ -92,27 +104,11 @@ export const useWs = () => {
       value: 10000,
     },
   ]);
-  const currentMaxBitrate = ref(maxBitrate.value[0].value);
-  const resolutionRatio = ref([
-    {
-      label: '360P',
-      value: 360,
-    },
-    {
-      label: '720P',
-      value: 720,
-    },
-    {
-      label: '1080P',
-      value: 1080,
-    },
+  const maxFramerate = ref([
     {
-      label: '1440P',
-      value: 1440,
+      label: '1帧',
+      value: 1,
     },
-  ]);
-  const currentResolutionRatio = ref(resolutionRatio.value[2].value);
-  const maxFramerate = ref([
     {
       label: '10帧',
       value: 10,
@@ -134,7 +130,43 @@ export const useWs = () => {
       value: 60,
     },
   ]);
-  const currentMaxFramerate = ref(maxFramerate.value[1].value);
+  const resolutionRatio = ref([
+    {
+      label: '160P',
+      value: 160,
+    },
+    {
+      label: '240P',
+      value: 240,
+    },
+    {
+      label: '360P',
+      value: 360,
+    },
+    {
+      label: '720P',
+      value: 720,
+    },
+    {
+      label: '1080P',
+      value: 1080,
+    },
+    {
+      label: '1440P',
+      value: 1440,
+    },
+    {
+      label: '1920P',
+      value: 1920,
+    },
+    {
+      label: '2400P',
+      value: 2400,
+    },
+  ]);
+  const currentMaxBitrate = ref(maxBitrate.value[3].value);
+  const currentResolutionRatio = ref(resolutionRatio.value[3].value);
+  const currentMaxFramerate = ref(maxFramerate.value[2].value);
 
   const damuList = ref<IDanmu[]>([]);
 
@@ -146,9 +178,6 @@ export const useWs = () => {
       newTrack.forEach((item) => {
         mixedStream.addTrack(item.track);
       });
-      // oldTrack.forEach((item) => {
-      //   mixedStream.addTrack(item.track);
-      // });
       console.log('新的allTrack音频轨', mixedStream.getAudioTracks());
       console.log('新的allTrack视频轨', mixedStream.getVideoTracks());
       console.log('旧的allTrack音频轨', localStream.value?.getAudioTracks());
@@ -170,42 +199,55 @@ export const useWs = () => {
   );
 
   watch(
-    () => currentMaxFramerate.value,
+    () => currentResolutionRatio.value,
     (newVal) => {
+      appStore.allTrack.forEach((info) => {
+        info.track.applyConstraints({
+          frameRate: { max: currentMaxFramerate.value },
+          height: newVal,
+        });
+      });
       networkStore.rtcMap.forEach(async (rtc) => {
-        const res = await rtc.setMaxFramerate(newVal);
+        const res = await rtc.setResolutionRatio(newVal);
         if (res === 1) {
-          window.$message.success('切换帧率成功!');
+          window.$message.success('切换分辨率成功!');
         } else {
-          window.$message.success('切换帧率失败!');
+          window.$message.success('切换分辨率失败!');
         }
       });
     }
   );
 
   watch(
-    () => currentMaxBitrate.value,
+    () => currentMaxFramerate.value,
     (newVal) => {
+      console.log(currentMaxFramerate.value, 'currentMaxFramerate.value');
+      appStore.allTrack.forEach((info) => {
+        info.track.applyConstraints({
+          frameRate: { max: newVal },
+          height: currentResolutionRatio.value,
+        });
+      });
       networkStore.rtcMap.forEach(async (rtc) => {
-        const res = await rtc.setMaxBitrate(newVal);
+        const res = await rtc.setMaxFramerate(newVal);
         if (res === 1) {
-          window.$message.success('切换码率成功!');
+          window.$message.success('切换率成功!');
         } else {
-          window.$message.success('切换码率失败!');
+          window.$message.success('切换率失败!');
         }
       });
     }
   );
 
   watch(
-    () => currentResolutionRatio.value,
+    () => currentMaxBitrate.value,
     (newVal) => {
       networkStore.rtcMap.forEach(async (rtc) => {
-        const res = await rtc.setResolutionRatio(newVal);
+        const res = await rtc.setMaxBitrate(newVal);
         if (res === 1) {
-          window.$message.success('切换分辨率成功!');
+          window.$message.success('切换率成功!');
         } else {
-          window.$message.success('切换分辨率失败!');
+          window.$message.success('切换率失败!');
         }
       });
     }
@@ -218,6 +260,7 @@ export const useWs = () => {
           ?.getSenders()
           .find((sender) => sender.track?.id === addTrackInfo.track.id);
         if (!sender) {
+          console.log('ffff', sender);
           rtc.peerConnection?.addTrack(addTrackInfo.track, addTrackInfo.stream);
         }
       });
@@ -483,9 +526,9 @@ export const useWs = () => {
     if (isSRS.value) {
       console.warn('SRS开始new WebRTCClass', `${roomId.value}___${receiver!}`);
       rtc = new WebRTCClass({
-        maxBitrate: currentMaxBitrate.value,
-        maxFramerate: currentMaxFramerate.value,
-        resolutionRatio: currentResolutionRatio.value,
+        maxBitrate: isPull.value ? -1 : currentMaxBitrate.value,
+        maxFramerate: isPull.value ? -1 : currentMaxFramerate.value,
+        resolutionRatio: isPull.value ? -1 : currentResolutionRatio.value,
         roomId: `${roomId.value}___${receiver!}`,
         videoEl,
         isSRS: true,
@@ -523,9 +566,9 @@ export const useWs = () => {
     } else {
       console.warn('开始new WebRTCClass', `${roomId.value}___${receiver!}`);
       rtc = new WebRTCClass({
-        maxBitrate: currentMaxBitrate.value,
-        maxFramerate: currentMaxFramerate.value,
-        resolutionRatio: currentResolutionRatio.value,
+        maxBitrate: isPull.value ? -1 : currentMaxBitrate.value,
+        maxFramerate: isPull.value ? -1 : currentMaxFramerate.value,
+        resolutionRatio: isPull.value ? -1 : currentResolutionRatio.value,
         roomId: `${roomId.value}___${receiver!}`,
         videoEl,
         isSRS: false,

+ 45 - 18
src/network/webRTC.ts

@@ -112,6 +112,7 @@ export class WebRTCClass {
           type: MediaTypeEnum.screen,
           mediaName: '',
           streamid: stream.id,
+          trackid: track.id,
         });
       }
     });
@@ -126,6 +127,7 @@ export class WebRTCClass {
           type: MediaTypeEnum.microphone,
           mediaName: '',
           streamid: stream.id,
+          trackid: track.id,
         });
       }
     });
@@ -140,6 +142,7 @@ export class WebRTCClass {
           type: MediaTypeEnum.screen,
           mediaName: '',
           streamid: stream.id,
+          trackid: track.id,
         });
       }
     });
@@ -154,6 +157,7 @@ export class WebRTCClass {
           type: MediaTypeEnum.microphone,
           mediaName: '',
           streamid: stream.id,
+          trackid: track.id,
         });
       }
     });
@@ -176,10 +180,11 @@ export class WebRTCClass {
   /** 设置分辨率 */
   setResolutionRatio = (height: number) => {
     console.log('开始设置分辨率', height);
+    console.log('旧的分辨率', this.resolutionRatio);
     return new Promise((resolve) => {
       this.localStream?.getTracks().forEach((track) => {
         if (track.kind === 'video') {
-          console.log('设置分辨率ing');
+          console.log('设置分辨率ing', track.id);
           track
             .applyConstraints({
               height,
@@ -198,26 +203,31 @@ export class WebRTCClass {
     });
   };
 
-  /** 设置最大码率 */
-  setMaxBitrate = (maxBitrate: number) => {
-    console.log('开始设置最大码率', maxBitrate);
+  /** 设置最大帧率 */
+  setMaxFramerate = (maxFramerate: number) => {
+    console.log('开始设置最大帧率', maxFramerate);
+    console.log('旧的最大帧率', this.maxFramerate);
     return new Promise<number>((resolve) => {
       this.peerConnection?.getSenders().forEach((sender) => {
         if (sender.track?.kind === 'video') {
-          console.log('设置最大码率ing');
+          console.log('设置最大帧率ing', sender.track.id);
           const parameters = { ...sender.getParameters() };
           if (parameters.encodings[0]) {
-            const val = 1000 * maxBitrate;
-            parameters.encodings[0].maxBitrate = val;
+            if (parameters.encodings[0].maxFramerate === maxFramerate) {
+              console.log('最大帧率不变,不设置');
+              resolve(1);
+              return;
+            }
+            parameters.encodings[0].maxFramerate = maxFramerate;
             sender
               .setParameters(parameters)
               .then(() => {
-                console.log('设置最大码率成功');
-                this.maxBitrate = val;
+                console.log('设置最大帧率成功', maxFramerate);
+                this.maxFramerate = maxFramerate;
                 resolve(1);
               })
               .catch((error) => {
-                console.error('设置最大码率失败', maxBitrate, error);
+                console.error('设置最大帧率失败', maxFramerate, error);
                 resolve(0);
               });
           }
@@ -226,25 +236,33 @@ export class WebRTCClass {
     });
   };
 
-  /** 设置最大帧率 */
-  setMaxFramerate = (maxFramerate: number) => {
-    console.log('开始设置最大帧率', maxFramerate);
+  /** 设置最大码率 */
+  setMaxBitrate = (maxBitrate: number) => {
+    console.log('开始设置最大码率', maxBitrate);
+    console.log('旧的最大码率', this.maxBitrate);
     return new Promise<number>((resolve) => {
       this.peerConnection?.getSenders().forEach((sender) => {
         if (sender.track?.kind === 'video') {
-          console.log('设置最大帧率ing');
+          console.log('设置最大码率ing', sender.track.id);
           const parameters = { ...sender.getParameters() };
           if (parameters.encodings[0]) {
-            parameters.encodings[0].maxFramerate = maxFramerate;
+            const val = 1000 * maxBitrate;
+            console.log(parameters.encodings[0].maxBitrate, val, 23223);
+            if (parameters.encodings[0].maxBitrate === val) {
+              console.log('最大码率不变,不设置');
+              resolve(1);
+              return;
+            }
+            parameters.encodings[0].maxBitrate = val;
             sender
               .setParameters(parameters)
               .then(() => {
-                console.log('设置最大帧率成功');
-                this.maxFramerate = maxFramerate;
+                console.log('设置最大码率成功', maxBitrate);
+                this.maxBitrate = val;
                 resolve(1);
               })
               .catch((error) => {
-                console.error('设置最大帧率失败', maxFramerate, error);
+                console.error('设置最大码率失败', maxBitrate, error);
                 resolve(0);
               });
           }
@@ -444,6 +462,15 @@ export class WebRTCClass {
         if (connectionState === 'connected') {
           // 表示每一个 ICE 连接要么正在使用(connected 或 completed 状态),要么已被关闭(closed 状态);并且,至少有一个连接处于 connected 或 completed 状态。
           console.warn(this.roomId, 'connectionState:connected');
+          if (this.maxBitrate !== -1) {
+            this.setMaxBitrate(this.maxBitrate);
+          }
+          if (this.maxFramerate !== -1) {
+            this.setMaxFramerate(this.maxFramerate);
+          }
+          if (this.resolutionRatio !== -1) {
+            this.setResolutionRatio(this.resolutionRatio);
+          }
         }
         if (connectionState === 'disconnected') {
           // 表示至少有一个 ICE 连接处于 disconnected 状态,并且没有连接处于 failed、connecting 或 checking 状态。

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

@@ -17,6 +17,7 @@ export type AppRootState = {
     track: MediaStreamTrack;
     stream: MediaStream;
     streamid: string;
+    trackid: string;
   }[];
 };
 

+ 41 - 36
src/views/home/index.vue

@@ -153,12 +153,12 @@
 </template>
 
 <script lang="ts" setup>
-import { isMobile, judgeDevice } from 'billd-utils';
+import { isMobile } from 'billd-utils';
 import { nextTick, onMounted, ref } from 'vue';
 import { useRouter } from 'vue-router';
 
 import { fetchLiveList } from '@/api/live';
-import { flvJs, useFlvPlay, useHlsPlay } from '@/hooks/use-play';
+import { useFlvPlay, useHlsPlay } from '@/hooks/use-play';
 import { ILive, ILiveRoom, LiveRoomTypeEnum, liveTypeEnum } from '@/interface';
 import { routerName } from '@/router';
 import { videoToCanvas } from '@/utils';
@@ -171,7 +171,7 @@ const otherLiveRoomList = ref<ILive[]>([]);
 const currentLiveRoom = ref<ILive>();
 
 const { flvVideoEl, startFlvPlay, destroyFlv } = useFlvPlay();
-const { startHlsPlay, destroyHls } = useHlsPlay();
+const { hlsVideoEl, startHlsPlay, destroyHls } = useHlsPlay();
 
 async function changeLiveRoom(item: ILive) {
   if (item.id === currentLiveRoom.value?.id) return;
@@ -185,24 +185,25 @@ async function changeLiveRoom(item: ILive) {
     item.live_room?.type === LiveRoomTypeEnum.system
   ) {
     // @ts-ignore
-    if (flvJs.isSupported()) {
-      const { width, height } = await startFlvPlay({
-        flvurl: item.live_room.flv_url!,
-      });
-      videoToCanvas({
-        videoEl: flvVideoEl.value!,
-        targetEl: canvasRef.value!,
-        width,
-        height,
-      });
-    } else {
-      destroyHls();
-      await startHlsPlay({
-        hlsurl: item.live_room.hls_url!,
-      });
-    }
+    // if (flvJs.isSupported()) {
+    //   const { width, height } = await startFlvPlay({
+    //     flvurl: item.live_room.flv_url!,
+    //   });
+    //   videoToCanvas({
+    //     videoEl: flvVideoEl.value!,
+    //     targetEl: canvasRef.value!,
+    //     width,
+    //     height,
+    //   });
+    // } else {
+    destroyHls();
+    await startHlsPlay({
+      hlsurl: item.live_room.hls_url!,
+    });
+    // }
   } else {
     destroyFlv();
+    destroyHls();
   }
 }
 
@@ -226,23 +227,27 @@ async function getLiveRoomList() {
               LiveRoomTypeEnum.user_obs ||
             currentLiveRoom.value?.live_room?.type === LiveRoomTypeEnum.system
           ) {
-            if (judgeDevice().isIphone) {
-              await startHlsPlay({
-                hlsurl: currentLiveRoom.value.live_room.hls_url!,
-              });
-            } else {
-              const { width, height } = await startFlvPlay({
-                flvurl: currentLiveRoom.value.live_room.flv_url!,
-              });
-              videoToCanvas({
-                videoEl: flvVideoEl.value!,
-                targetEl: canvasRef.value!,
-                width,
-                height,
-              });
-            }
-          } else {
-            destroyFlv();
+            // if (judgeDevice().isIphone) {
+            const { width, height } = await startHlsPlay({
+              hlsurl: currentLiveRoom.value.live_room.hls_url!,
+            });
+            videoToCanvas({
+              videoEl: hlsVideoEl.value!,
+              targetEl: canvasRef.value!,
+              width,
+              height,
+            });
+            // } else {
+            //   const { width, height } = await startFlvPlay({
+            //     flvurl: currentLiveRoom.value.live_room.flv_url!,
+            //   });
+            //   videoToCanvas({
+            //     videoEl: flvVideoEl.value!,
+            //     targetEl: canvasRef.value!,
+            //     width,
+            //     height,
+            //   });
+            // }
           }
         });
       }

+ 10 - 6
src/views/push/index.vue

@@ -358,7 +358,7 @@ async function addMediaOk(val: {
       video: {
         deviceId: val.deviceId,
         height: currentResolutionRatio.value,
-        frameRate: { ideal: currentMaxFramerate.value, max: 90 },
+        frameRate: { max: currentMaxFramerate.value },
       },
       audio: true,
     });
@@ -371,6 +371,7 @@ async function addMediaOk(val: {
       track: event.getVideoTracks()[0],
       stream: event,
       streamid: event.id,
+      trackid: event.getVideoTracks()[0].id,
     };
     const audio = event.getAudioTracks();
     if (audio.length) {
@@ -381,7 +382,7 @@ async function addMediaOk(val: {
         window.$message.error('srs模式最多只能有一个音频');
         return;
       }
-      const autioTrack = {
+      const audioTrack = {
         id: getRandomString(8),
         audio: 1,
         video: 2,
@@ -390,10 +391,11 @@ async function addMediaOk(val: {
         track: event.getAudioTracks()[0],
         stream: event,
         streamid: event.id,
+        trackid: event.getAudioTracks()[0].id,
       };
-      appStore.setAllTrack([...appStore.allTrack, videoTrack, autioTrack]);
+      appStore.setAllTrack([...appStore.allTrack, videoTrack, audioTrack]);
       addTrack(videoTrack);
-      addTrack(autioTrack);
+      addTrack(audioTrack);
     } else {
       if (
         isSRS &&
@@ -412,7 +414,7 @@ async function addMediaOk(val: {
       video: {
         deviceId: val.deviceId,
         height: currentResolutionRatio.value,
-        frameRate: { ideal: currentMaxFramerate.value, max: 90 },
+        frameRate: { max: currentMaxFramerate.value },
       },
       audio: false,
     });
@@ -432,6 +434,7 @@ async function addMediaOk(val: {
       track: event.getVideoTracks()[0],
       stream: event,
       streamid: event.id,
+      trackid: event.getVideoTracks()[0].id,
     };
     appStore.setAllTrack([...appStore.allTrack, track]);
     addTrack(track);
@@ -457,6 +460,7 @@ async function addMediaOk(val: {
       track: event.getAudioTracks()[0],
       stream: event,
       streamid: event.id,
+      trackid: event.getAudioTracks()[0].id,
     };
     appStore.setAllTrack([...appStore.allTrack, track]);
     addTrack(track);
@@ -618,7 +622,7 @@ function handleStartMedia(item: { type: MediaTypeEnum; txt: string }) {
             width: 80px;
           }
           .down {
-            width: 80px;
+            width: 90px;
 
             user-select: none;
           }