Browse Source

合并更新

lex 11 months ago
parent
commit
e59d90558f

+ 7 - 0
src/views/courseware-play/component/audio-item/index.module.less

@@ -97,6 +97,13 @@
       margin: 4px 16px 4px 0;
     }
 
+    .downloadSpeed {
+      font-weight: 600;
+      font-size: 14Px;
+      color: #FFFFFF;
+      line-height: 25px;
+    }
+
     .actionBtn>img {
       width: 100%;
       height: 100%;

+ 100 - 2
src/views/courseware-play/component/audio-item/index.tsx

@@ -1,4 +1,11 @@
-import { defineComponent, nextTick, reactive, toRefs, watch } from 'vue';
+import {
+  defineComponent,
+  nextTick,
+  onMounted,
+  reactive,
+  toRefs,
+  watch
+} from 'vue';
 import { ref } from 'vue';
 import styles from './index.module.less';
 
@@ -42,6 +49,7 @@ export default defineComponent({
   setup(props, { emit }) {
     const { item, isEmtry } = toRefs(props);
     const data = reactive({
+      speedInKbps: '0 KB/s',
       timer: null as any,
       currentTime: 0,
       duration: 0.1,
@@ -163,7 +171,7 @@ export default defineComponent({
       //     onInit(audioRef.value, canvasRef.value);
       //   };
       // }
-      emit('loadedmetadata', audioRef.value)
+      emit('loadedmetadata', audioRef.value);
     };
 
     /** 改变播放时间 */
@@ -208,6 +216,94 @@ export default defineComponent({
       });
       vudio1.dance();
     });
+
+    const calculateSpeed = (element: any) => {
+      let previousBytesLoaded = 0;
+      let timer: any = null;
+      let previousTime = Date.now();
+
+      // 缓存检测状态
+      let isBuffering = false;
+      // 缓存检测计时器
+      let bufferTimeout: any = null;
+      // 设定一个检测缓存停止的时间间隔,这里我们设置为2500毫秒(2秒)
+      const BUFFER_CHECK_INTERVAL = 2500;
+
+      function resetDownloadSpeed() {
+        timer = setTimeout(() => {
+          // displayElement.textContent = `视屏下载速度: 0 KB/s`;
+          data.speedInKbps = `0 KB/s`;
+        }, 1500);
+      }
+
+      function buffterCatch() {
+        // 设定一个计时器,检查是否在指定的时间内再次触发了progress事件
+        bufferTimeout = setTimeout(() => {
+          if (isBuffering) {
+            // 如果计时器到达且isBuffering仍为true,则认为缓存停止
+            console.log('停止缓存数据。');
+            isBuffering = false;
+            data.speedInKbps = '';
+          }
+        }, BUFFER_CHECK_INTERVAL);
+      }
+
+      element.addEventListener('progress', () => {
+        const currentTime = Date.now();
+        const buffered = element.buffered;
+        let currentBytesLoaded = 0;
+
+        if (buffered.length > 0) {
+          for (let i = 0; i < buffered.length; i++) {
+            currentBytesLoaded += buffered.end(i) - buffered.start(i);
+          }
+          currentBytesLoaded *= element.duration * element.seekable.end(0); // 更精确地近似字节加载量
+        }
+
+        // console.log(
+        //   'progress',
+        //   currentBytesLoaded,
+        //   previousBytesLoaded,
+        //   currentBytesLoaded > previousBytesLoaded
+        // );
+        if (currentBytesLoaded > previousBytesLoaded) {
+          const timeDiff = (currentTime - previousTime) / 1000; // 时间差转换为秒
+          const bytesDiff = currentBytesLoaded - previousBytesLoaded; // 字节差值
+          const speed = bytesDiff / timeDiff; // 字节每秒
+
+          const kbps = speed / 1024;
+          console.log(kbps, speed);
+          const speedInKbps = kbps.toFixed(2); // 转换为千字节每秒并保留两位小数
+          if (kbps > 1024) {
+            data.speedInKbps = `${Number((kbps / 1024).toFixed(2))} M/s`;
+          } else {
+            data.speedInKbps = `${Number(speedInKbps)} KB/s`;
+          }
+
+          previousBytesLoaded = currentBytesLoaded;
+          previousTime = currentTime;
+
+          // 如果1秒钟没有返回就重置数据
+          clearTimeout(timer);
+          resetDownloadSpeed();
+        }
+
+        // 如果有缓存检测计时器,则清除它
+        if (bufferTimeout) {
+          clearTimeout(bufferTimeout);
+        }
+        // 标记为正在缓存
+        isBuffering = true;
+
+        buffterCatch();
+      });
+    };
+
+    onMounted(() => {
+      nextTick(() => {
+        calculateSpeed(audioRef.value);
+      });
+    });
     return () => (
       <div class={styles.videoWrap}>
         <div class={styles.content}>
@@ -301,6 +397,8 @@ export default defineComponent({
               }}>
               <img src={data.loop ? iconLoopActive : iconLoop} />
             </div>
+
+            <div class={styles.downloadSpeed}>{data.speedInKbps}</div>
           </div>
         </div>
       </div>

+ 7 - 0
src/views/courseware-play/component/video-item/index.module.less

@@ -81,6 +81,13 @@
       display: flex;
     }
 
+    .downloadSpeed {
+      font-weight: 600;
+      font-size: 14Px;
+      color: #FFFFFF;
+      line-height: 25px;
+    }
+
     .actionBtn {
       display: flex;
       width: 24px;

+ 98 - 2
src/views/courseware-play/component/video-item/index.tsx

@@ -46,13 +46,23 @@ export default defineComponent({
       default: false
     }
   },
-  emits: ['canplay', 'pause', 'togglePlay', 'ended', 'reset', 'close', 'error', 'loadedmetadata'],
+  emits: [
+    'canplay',
+    'pause',
+    'togglePlay',
+    'ended',
+    'reset',
+    'close',
+    'error',
+    'loadedmetadata'
+  ],
   setup(props, { emit, expose }) {
     const videoID = 'video' + Date.now() + Math.floor(Math.random() * 100);
     const speedBtnId = 'speed' + Date.now() + Math.floor(Math.random() * 100);
     const videoItem = ref();
     const { item, isEmtry } = toRefs(props);
     const data = reactive({
+      speedInKbps: '0 KB/s',
       timer: null as any,
       currentTime: 0,
       duration: 0,
@@ -66,6 +76,7 @@ export default defineComponent({
       },
       defaultSpeed: 1 // 默认速度
     });
+    const videoRef = ref();
     const contetRef = ref();
 
     watch(
@@ -166,7 +177,7 @@ export default defineComponent({
               nextTick(handlePlayVideo);
             });
           }
-          emit('loadedmetadata', videoItem.value)
+          emit('loadedmetadata', videoItem.value);
         });
         // 视频开始播放
         videoItem.value.on('play', () => {
@@ -228,6 +239,84 @@ export default defineComponent({
       }
     );
 
+    const calculateSpeed = (element: any) => {
+      let previousBytesLoaded = 0;
+      let timer: any = null;
+      let previousTime = Date.now();
+
+      // 缓存检测状态
+      let isBuffering = false;
+      // 缓存检测计时器
+      let bufferTimeout: any = null;
+      // 设定一个检测缓存停止的时间间隔,这里我们设置为2500毫秒(2秒)
+      const BUFFER_CHECK_INTERVAL = 2500;
+
+      function resetDownloadSpeed() {
+        timer = setTimeout(() => {
+          // displayElement.textContent = `视屏下载速度: 0 KB/s`;
+          data.speedInKbps = `0 KB/s`;
+        }, 1500);
+      }
+
+      function buffterCatch() {
+        // 设定一个计时器,检查是否在指定的时间内再次触发了progress事件
+        bufferTimeout = setTimeout(() => {
+          if (isBuffering) {
+            // 如果计时器到达且isBuffering仍为true,则认为缓存停止
+            console.log('停止缓存数据。');
+            isBuffering = false;
+            data.speedInKbps = '';
+          }
+        }, BUFFER_CHECK_INTERVAL);
+      }
+
+      element.addEventListener('progress', () => {
+        const currentTime = Date.now();
+        const buffered = element.buffered;
+        let currentBytesLoaded = 0;
+
+        if (buffered.length > 0) {
+          for (let i = 0; i < buffered.length; i++) {
+            currentBytesLoaded += buffered.end(i) - buffered.start(i);
+          }
+          currentBytesLoaded *= element.duration * element.seekable.end(0); // 更精确地近似字节加载量
+        }
+
+        console.log('progress', currentBytesLoaded > previousBytesLoaded);
+        if (currentBytesLoaded > previousBytesLoaded) {
+          const timeDiff = (currentTime - previousTime) / 1000; // 时间差转换为秒
+          const bytesDiff = currentBytesLoaded - previousBytesLoaded; // 字节差值
+          const speed = bytesDiff / timeDiff; // 字节每秒
+
+          console.log(timeDiff, bytesDiff, speed);
+
+          const kbps = speed / 1024;
+          const speedInKbps = kbps.toFixed(2); // 转换为千字节每秒并保留两位小数
+          if (kbps > 1024) {
+            data.speedInKbps = `${Number((kbps / 1024).toFixed(2))} M/s`;
+          } else {
+            data.speedInKbps = `${Number(speedInKbps)} KB/s`;
+          }
+
+          previousBytesLoaded = currentBytesLoaded;
+          previousTime = currentTime;
+
+          // 如果1秒钟没有返回就重置数据
+          clearTimeout(timer);
+          resetDownloadSpeed();
+        }
+
+        // 如果有缓存检测计时器,则清除它
+        if (bufferTimeout) {
+          clearTimeout(bufferTimeout);
+        }
+        // 标记为正在缓存
+        isBuffering = true;
+
+        buffterCatch();
+      });
+    };
+
     onMounted(() => {
       videoItem.value = TCPlayer(videoID, {
         appID: '',
@@ -239,6 +328,10 @@ export default defineComponent({
         e.stopPropagation();
         data.speedControl = !data.speedControl;
       });
+
+      nextTick(() => {
+        calculateSpeed(videoRef.value);
+      });
     });
 
     const pause = () => {
@@ -256,6 +349,7 @@ export default defineComponent({
             <video
               style={{ width: '100%', height: '100%' }}
               id={videoID}
+              ref={videoRef}
               preload="auto"
               playsinline
               webkit-playsinline
@@ -319,6 +413,8 @@ export default defineComponent({
             <div class={styles.actionBtn} id={speedBtnId}>
               <img src={iconSpeed} />
             </div>
+
+            <div class={styles.downloadSpeed}>{data.speedInKbps}</div>
           </div>
         </div>