Przeglądaj źródła

1、视频切片加载,使用video.js

liyanbo 9 miesięcy temu
rodzic
commit
8bfb8f51b7
3 zmienionych plików z 240 dodań i 6 usunięć
  1. 214 1
      package-lock.json
  2. 1 0
      package.json
  3. 25 5
      src/views/AIDevelop.vue

+ 214 - 1
package-lock.json

@@ -18,6 +18,7 @@
         "jsencrypt": "^3.3.2",
         "markdown-it": "^14.1.0",
         "router": "^2.2.0",
+        "video.js": "^8.23.3",
         "vue": "^3.5.17",
         "vue-router": "^4.5.1",
         "vuex": "^4.0.2",
@@ -1425,6 +1426,15 @@
         "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
       }
     },
+    "node_modules/@babel/runtime": {
+      "version": "7.27.6",
+      "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.27.6.tgz",
+      "integrity": "sha512-vbavdySgbTTrmFE+EsiqUTzlOr5bzlnJtUv9PynGCAKvfQqjIXbvFdumPM/GxMDfyuGMJaJAU6TO4zc1Jf1i8Q==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=6.9.0"
+      }
+    },
     "node_modules/@babel/template": {
       "version": "7.27.2",
       "resolved": "https://registry.npmmirror.com/@babel/template/-/template-7.27.2.tgz",
@@ -2601,6 +2611,54 @@
       "integrity": "sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==",
       "license": "MIT"
     },
+    "node_modules/@videojs/http-streaming": {
+      "version": "3.17.0",
+      "resolved": "https://registry.npmjs.org/@videojs/http-streaming/-/http-streaming-3.17.0.tgz",
+      "integrity": "sha512-Ch1P3tvvIEezeZXyK11UfWgp4cWKX4vIhZ30baN/lRinqdbakZ5hiAI3pGjRy3d+q/Epyc8Csz5xMdKNNGYpcw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@videojs/vhs-utils": "^4.1.1",
+        "aes-decrypter": "^4.0.2",
+        "global": "^4.4.0",
+        "m3u8-parser": "^7.2.0",
+        "mpd-parser": "^1.3.1",
+        "mux.js": "7.1.0",
+        "video.js": "^7 || ^8"
+      },
+      "engines": {
+        "node": ">=8",
+        "npm": ">=5"
+      },
+      "peerDependencies": {
+        "video.js": "^8.19.0"
+      }
+    },
+    "node_modules/@videojs/vhs-utils": {
+      "version": "4.1.1",
+      "resolved": "https://registry.npmjs.org/@videojs/vhs-utils/-/vhs-utils-4.1.1.tgz",
+      "integrity": "sha512-5iLX6sR2ownbv4Mtejw6Ax+naosGvoT9kY+gcuHzANyUZZ+4NpeNdKMUhb6ag0acYej1Y7cmr/F2+4PrggMiVA==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "global": "^4.4.0"
+      },
+      "engines": {
+        "node": ">=8",
+        "npm": ">=5"
+      }
+    },
+    "node_modules/@videojs/xhr": {
+      "version": "2.7.0",
+      "resolved": "https://registry.npmjs.org/@videojs/xhr/-/xhr-2.7.0.tgz",
+      "integrity": "sha512-giab+EVRanChIupZK7gXjHy90y3nncA2phIOyG3Ne5fvpiMJzvqYwiTOnEVW2S4CoYcuKJkomat7bMXA/UoUZQ==",
+      "license": "MIT",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5",
+        "global": "~4.4.0",
+        "is-function": "^1.0.1"
+      }
+    },
     "node_modules/@vitejs/plugin-legacy": {
       "version": "7.0.1",
       "resolved": "https://registry.npmmirror.com/@vitejs/plugin-legacy/-/plugin-legacy-7.0.1.tgz",
@@ -2840,6 +2898,15 @@
         }
       }
     },
+    "node_modules/@xmldom/xmldom": {
+      "version": "0.8.10",
+      "resolved": "https://registry.npmjs.org/@xmldom/xmldom/-/xmldom-0.8.10.tgz",
+      "integrity": "sha512-2WALfTl4xo2SkGCYRt6rDTFfk9R1czmBvUQy12gK2KuRKIpWEhcbbzy8EZXtz/jkRqHX8bFEc6FC1HjX4TUWYw==",
+      "license": "MIT",
+      "engines": {
+        "node": ">=10.0.0"
+      }
+    },
     "node_modules/acorn": {
       "version": "8.15.0",
       "resolved": "https://registry.npmmirror.com/acorn/-/acorn-8.15.0.tgz",
@@ -2853,6 +2920,18 @@
         "node": ">=0.4.0"
       }
     },
+    "node_modules/aes-decrypter": {
+      "version": "4.0.2",
+      "resolved": "https://registry.npmjs.org/aes-decrypter/-/aes-decrypter-4.0.2.tgz",
+      "integrity": "sha512-lc+/9s6iJvuaRe5qDlMTpCFjnwpkeOXp8qP3oiZ5jsj1MRg+SBVUmmICrhxHvc8OELSmc+fEyyxAuppY6hrWzw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@videojs/vhs-utils": "^4.1.1",
+        "global": "^4.4.0",
+        "pkcs7": "^1.0.4"
+      }
+    },
     "node_modules/argparse": {
       "version": "2.0.1",
       "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
@@ -3149,6 +3228,11 @@
         "node": ">=0.10"
       }
     },
+    "node_modules/dom-walk": {
+      "version": "0.1.2",
+      "resolved": "https://registry.npmjs.org/dom-walk/-/dom-walk-0.1.2.tgz",
+      "integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
+    },
     "node_modules/dunder-proto": {
       "version": "1.0.1",
       "resolved": "https://registry.npmmirror.com/dunder-proto/-/dunder-proto-1.0.1.tgz",
@@ -3454,6 +3538,16 @@
         "node": ">= 0.4"
       }
     },
+    "node_modules/global": {
+      "version": "4.4.0",
+      "resolved": "https://registry.npmjs.org/global/-/global-4.4.0.tgz",
+      "integrity": "sha512-wv/LAoHdRE3BeTGz53FAamhGlPLhlssK45usmGFThIi4XqnBmjKQ16u+RNbP7WvigRZDxUsM0J3gcQ5yicaL0w==",
+      "license": "MIT",
+      "dependencies": {
+        "min-document": "^2.19.0",
+        "process": "^0.11.10"
+      }
+    },
     "node_modules/gopd": {
       "version": "1.2.0",
       "resolved": "https://registry.npmmirror.com/gopd/-/gopd-1.2.0.tgz",
@@ -3559,6 +3653,12 @@
         "node": ">=0.10.0"
       }
     },
+    "node_modules/is-function": {
+      "version": "1.0.2",
+      "resolved": "https://registry.npmjs.org/is-function/-/is-function-1.0.2.tgz",
+      "integrity": "sha512-lw7DUp0aWXYg+CBCN+JKkcE0Q2RayZnSvnZBlwgxHBQhqt5pZNVy4Ri7H9GmmXkdu7LUthszM+Tor1u/2iBcpQ==",
+      "license": "MIT"
+    },
     "node_modules/is-glob": {
       "version": "4.0.3",
       "resolved": "https://registry.npmmirror.com/is-glob/-/is-glob-4.0.3.tgz",
@@ -3671,6 +3771,17 @@
         "yallist": "^3.0.2"
       }
     },
+    "node_modules/m3u8-parser": {
+      "version": "7.2.0",
+      "resolved": "https://registry.npmjs.org/m3u8-parser/-/m3u8-parser-7.2.0.tgz",
+      "integrity": "sha512-CRatFqpjVtMiMaKXxNvuI3I++vUumIXVVT/JpCpdU/FynV/ceVw1qpPyyBNindL+JlPMSesx+WX1QJaZEJSaMQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@videojs/vhs-utils": "^4.1.1",
+        "global": "^4.4.0"
+      }
+    },
     "node_modules/magic-string": {
       "version": "0.30.17",
       "resolved": "https://registry.npmmirror.com/magic-string/-/magic-string-0.30.17.tgz",
@@ -3778,12 +3889,52 @@
         "node": ">= 0.6"
       }
     },
+    "node_modules/min-document": {
+      "version": "2.19.0",
+      "resolved": "https://registry.npmjs.org/min-document/-/min-document-2.19.0.tgz",
+      "integrity": "sha512-9Wy1B3m3f66bPPmU5hdA4DR4PB2OfDU/+GS3yAB7IQozE3tqXaVv2zOjgla7MEGSRv95+ILmOuvhLkOK6wJtCQ==",
+      "dependencies": {
+        "dom-walk": "^0.1.0"
+      }
+    },
+    "node_modules/mpd-parser": {
+      "version": "1.3.1",
+      "resolved": "https://registry.npmjs.org/mpd-parser/-/mpd-parser-1.3.1.tgz",
+      "integrity": "sha512-1FuyEWI5k2HcmhS1HkKnUAQV7yFPfXPht2DnRRGtoiiAAW+ESTbtEXIDpRkwdU+XyrQuwrIym7UkoPKsZ0SyFw==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@videojs/vhs-utils": "^4.0.0",
+        "@xmldom/xmldom": "^0.8.3",
+        "global": "^4.4.0"
+      },
+      "bin": {
+        "mpd-to-m3u8-json": "bin/parse.js"
+      }
+    },
     "node_modules/ms": {
       "version": "2.1.3",
       "resolved": "https://registry.npmmirror.com/ms/-/ms-2.1.3.tgz",
       "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
       "license": "MIT"
     },
+    "node_modules/mux.js": {
+      "version": "7.1.0",
+      "resolved": "https://registry.npmjs.org/mux.js/-/mux.js-7.1.0.tgz",
+      "integrity": "sha512-NTxawK/BBELJrYsZThEulyUMDVlLizKdxyAsMuzoCD1eFj97BVaA8D/CvKsKu6FOLYkFojN5CbM9h++ZTZtknA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.11.2",
+        "global": "^4.4.0"
+      },
+      "bin": {
+        "muxjs-transmux": "bin/transmux.js"
+      },
+      "engines": {
+        "node": ">=8",
+        "npm": ">=5"
+      }
+    },
     "node_modules/nanoid": {
       "version": "3.3.11",
       "resolved": "https://registry.npmmirror.com/nanoid/-/nanoid-3.3.11.tgz",
@@ -3874,6 +4025,18 @@
         "url": "https://github.com/sponsors/jonschlinkert"
       }
     },
+    "node_modules/pkcs7": {
+      "version": "1.0.4",
+      "resolved": "https://registry.npmjs.org/pkcs7/-/pkcs7-1.0.4.tgz",
+      "integrity": "sha512-afRERtHn54AlwaF2/+LFszyAANTCggGilmcmILUzEjvs3XgFZT+xE6+QWQcAGmu4xajy+Xtj7acLOPdx5/eXWQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.5.5"
+      },
+      "bin": {
+        "pkcs7": "bin/cli.js"
+      }
+    },
     "node_modules/postcss": {
       "version": "8.5.6",
       "resolved": "https://registry.npmmirror.com/postcss/-/postcss-8.5.6.tgz",
@@ -3906,7 +4069,6 @@
       "version": "0.11.10",
       "resolved": "https://registry.npmmirror.com/process/-/process-0.11.10.tgz",
       "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
-      "dev": true,
       "license": "MIT",
       "engines": {
         "node": ">= 0.6.0"
@@ -4306,6 +4468,57 @@
         "inherits": "2.0.3"
       }
     },
+    "node_modules/video.js": {
+      "version": "8.23.3",
+      "resolved": "https://registry.npmjs.org/video.js/-/video.js-8.23.3.tgz",
+      "integrity": "sha512-Toe0VLlDZcUhiaWfcePS1OEdT3ATfktm0hk/PELfD7zUoPDHeT+cJf/wZmCy5M5eGVwtGUg25RWPCj1L/1XufA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "@babel/runtime": "^7.12.5",
+        "@videojs/http-streaming": "^3.17.0",
+        "@videojs/vhs-utils": "^4.1.1",
+        "@videojs/xhr": "2.7.0",
+        "aes-decrypter": "^4.0.2",
+        "global": "4.4.0",
+        "m3u8-parser": "^7.2.0",
+        "mpd-parser": "^1.3.1",
+        "mux.js": "^7.0.1",
+        "videojs-contrib-quality-levels": "4.1.0",
+        "videojs-font": "4.2.0",
+        "videojs-vtt.js": "0.15.5"
+      }
+    },
+    "node_modules/videojs-contrib-quality-levels": {
+      "version": "4.1.0",
+      "resolved": "https://registry.npmjs.org/videojs-contrib-quality-levels/-/videojs-contrib-quality-levels-4.1.0.tgz",
+      "integrity": "sha512-TfrXJJg1Bv4t6TOCMEVMwF/CoS8iENYsWNKip8zfhB5kTcegiFYezEA0eHAJPU64ZC8NQbxQgOwAsYU8VXbOWA==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "global": "^4.4.0"
+      },
+      "engines": {
+        "node": ">=16",
+        "npm": ">=8"
+      },
+      "peerDependencies": {
+        "video.js": "^8"
+      }
+    },
+    "node_modules/videojs-font": {
+      "version": "4.2.0",
+      "resolved": "https://registry.npmjs.org/videojs-font/-/videojs-font-4.2.0.tgz",
+      "integrity": "sha512-YPq+wiKoGy2/M7ccjmlvwi58z2xsykkkfNMyIg4xb7EZQQNwB71hcSsB3o75CqQV7/y5lXkXhI/rsGAS7jfEmQ==",
+      "license": "Apache-2.0"
+    },
+    "node_modules/videojs-vtt.js": {
+      "version": "0.15.5",
+      "resolved": "https://registry.npmjs.org/videojs-vtt.js/-/videojs-vtt.js-0.15.5.tgz",
+      "integrity": "sha512-yZbBxvA7QMYn15Lr/ZfhhLPrNpI/RmCSCqgIff57GC2gIrV5YfyzLfLyZMj0NnZSAz8syB4N0nHXpZg9MyrMOQ==",
+      "license": "Apache-2.0",
+      "dependencies": {
+        "global": "^4.3.1"
+      }
+    },
     "node_modules/vite": {
       "version": "7.0.0",
       "resolved": "https://registry.npmmirror.com/vite/-/vite-7.0.0.tgz",

+ 1 - 0
package.json

@@ -19,6 +19,7 @@
     "jsencrypt": "^3.3.2",
     "markdown-it": "^14.1.0",
     "router": "^2.2.0",
+    "video.js": "^8.23.3",
     "vue": "^3.5.17",
     "vue-router": "^4.5.1",
     "vuex": "^4.0.2",

+ 25 - 5
src/views/AIDevelop.vue

@@ -94,7 +94,7 @@
         </div>
         <div class="box-video">
           <video
-            class="full-box-video"
+            class="full-box-video video-js vjs-default-skin"
             :src="course.courseVideoPath"
             controlsList="nodownload"
             controls
@@ -244,6 +244,12 @@
 <script setup>
 import { ref, onMounted,onUnmounted, onBeforeUnmount } from 'vue'
 import { useRouter } from 'vue-router'
+import videojs from 'video.js';
+import 'video.js/dist/video-js.css';
+import '@videojs/http-streaming'; // 支持HLS分片
+const videoPlayer = ref(null);
+let player = null;
+
 import {
   Expand,
   Fold,
@@ -266,9 +272,6 @@ import auto from '@/assets/icon/auto_awesome.png'
 import { ClassType } from '@/api/class.js'
 import { Message } from '@/utils/message/Message.js'
 
-// import Hls from 'hls.js'
-// let hls = null
-
 const router = useRouter() // 获取当前路由对象
 // 搜索框
 const SearchInput = ref('')
@@ -320,7 +323,7 @@ onMounted(async () => {
       //课程数据
       courseList.value.forEach((courseTemp,index) => {
         let menuIndex = courseTemp.courseLabel + '-' + (index+1);
-        // 填充大纲小节
+        //填充大纲小节
         let menu = menuItems.value.find(menu => courseTemp.courseLabel === menu.index);
         if (menu){//小节
           menu.children = menu.children || [];
@@ -361,6 +364,12 @@ onMounted(async () => {
   }
 })
 
+onUnmounted(() => {
+  if (player) {
+    player.dispose();
+  }
+});
+
 // 菜单打开和关闭的处理函数
 const handleOpen = () => {}
 const handleClose = () => {}
@@ -469,6 +478,16 @@ const tryPlayVideo = () => {
       console.error('视频播放失败,可能是浏览器自动播放限制:', error)
     })
   }
+  player = videojs(videoPlayer.value, {
+    controls: true,
+    sources: [
+      {
+        src: course.value.courseVideoPath,
+        type: 'video/mp4'
+      }
+    ],
+    preload:'metadata' // 仅加载元数据,避免预加载整个文件
+  });
 }
 
 // 检查视频播放权限
@@ -918,6 +937,7 @@ $text-color: #483d8b; // 文本颜色:靛蓝色
   height: rpx(300);
   video.full-box-video {
     height: rpx(280);
+    width: 67%;
     margin: 0 auto;
     border-radius: rpx(12);
     object-fit: cover;