From d5f9c53f99c192725bbd6f0c6beffec02b6c260c Mon Sep 17 00:00:00 2001 From: zhaotianzeng Date: Mon, 23 Dec 2024 11:11:22 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BF=AE=E6=94=B9=E4=BD=BF=E7=94=A8artplayer?= =?UTF-8?q?=E8=BF=9B=E8=A1=8C=E6=92=AD=E6=94=BE=EF=BC=8C=E6=94=AF=E6=8C=81?= =?UTF-8?q?hlv=E5=92=8Cm3u8=E6=A0=BC=E5=BC=8F=E6=92=AD=E6=94=BE=20?= =?UTF-8?q?=E6=94=AF=E6=8C=81=E4=BD=BF=E7=94=A8=E9=98=BF=E9=87=8C=E4=BA=91?= =?UTF-8?q?=E7=9B=98=E8=BF=9B=E8=A1=8C=E8=A7=A3=E7=A0=81=E6=92=AD=E6=94=BE?= =?UTF-8?q?=20=E8=B0=83=E7=94=A8=E6=9A=82=E5=81=9C=E7=9A=84=E6=97=B6?= =?UTF-8?q?=E5=80=99=EF=BC=8C=E8=BF=9B=E8=A1=8C=E4=BF=9D=E5=AD=98=E8=BF=9B?= =?UTF-8?q?=E5=BA=A6=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 5 +- package.json | 6 +- pnpm-lock.yaml | 155 +++++++++------------------------ src/api/alist.ts | 14 +++ src/components/VideoPlayer.vue | 135 ++++++++++++++-------------- src/types/alist.ts | 5 +- src/utils/progressManager.ts | 1 + src/views/CourseListView.vue | 1 - src/views/CourseView.vue | 67 ++++++++++---- 9 files changed, 184 insertions(+), 205 deletions(-) diff --git a/README.md b/README.md index 18c509e..69a314d 100644 --- a/README.md +++ b/README.md @@ -3,6 +3,7 @@ 一个基于 Alist 的在线课程视频播放器插件,支持课程目录浏览、视频播放和进度记录等功能。 受够了使用emby看课程,所以自己写一个。 + ## 功能特点 - 🎯 课程目录树形展示 @@ -17,7 +18,7 @@ - Vue 3 - TypeScript - Alist API -- xgplayer +- artplayer ## 快速开始 @@ -65,10 +66,8 @@ npm run build ## 运行效果 - [在线预览](https://www.ztianzeng.com/alist-course-plugin/) - ![截图](docs/config.png) ![截图](docs/list.png) diff --git a/package.json b/package.json index 4d1b2b0..cc41ca7 100644 --- a/package.json +++ b/package.json @@ -13,16 +13,18 @@ }, "dependencies": { "@element-plus/icons-vue": "^2.3.1", + "artplayer": "^5.2.1", "axios": "^1.7.9", "element-plus": "^2.9.1", + "flv.js": "^1.6.2", + "hls.js": "^1.5.18", "natural-orderby": "^5.0.0", "pinia": "^2.2.6", "video.js": "^8.21.0", "vite": "6.0.3", "vue": "^3.5.13", "vue-router": "^4.4.5", - "vue-tree-chart": "^1.2.9", - "xgplayer": "^3.0.20" + "vue-tree-chart": "^1.2.9" }, "devDependencies": { "@tsconfig/node22": "^22.0.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index fb1312b..81c266a 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -8,12 +8,21 @@ dependencies: '@element-plus/icons-vue': specifier: ^2.3.1 version: 2.3.1(vue@3.5.13) + artplayer: + specifier: ^5.2.1 + version: 5.2.1 axios: specifier: ^1.7.9 version: 1.7.9 element-plus: specifier: ^2.9.1 version: 2.9.1(vue@3.5.13) + flv.js: + specifier: ^1.6.2 + version: 1.6.2 + hls.js: + specifier: ^1.5.18 + version: 1.5.18 natural-orderby: specifier: ^5.0.0 version: 5.0.0 @@ -35,9 +44,6 @@ dependencies: vue-tree-chart: specifier: ^1.2.9 version: 1.2.9 - xgplayer: - specifier: ^3.0.20 - version: 3.0.20(core-js@3.39.0) devDependencies: '@tsconfig/node22': @@ -1928,6 +1934,12 @@ packages: resolution: {integrity: sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==} dev: true + /artplayer@5.2.1: + resolution: {integrity: sha512-xhNE9zSLT2z4O2CJwcMSWADsS3Cvq0PwNanvMzRsqgfUhsMOpum8HlMtIUPOTyMGjIhKV8sl109HFUalQK6WJQ==} + dependencies: + option-validator: 2.0.6 + dev: false + /async-validator@4.2.5: resolution: {integrity: sha512-7HhHjtERjqlNbZtqNqy2rckN/SpOOlmDliet+lP7k+eKZEjPk3DgyeU9lIXLdeLz0uBbbVp+9Qdow9wJWgwwfg==} dev: false @@ -2094,11 +2106,6 @@ packages: is-what: 4.1.16 dev: true - /core-js@3.39.0: - resolution: {integrity: sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==} - requiresBuild: true - dev: false - /cross-spawn@7.0.6: resolution: {integrity: sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==} engines: {node: '>= 8'} @@ -2125,20 +2132,6 @@ packages: /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - /d@1.0.2: - resolution: {integrity: sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==} - engines: {node: '>=0.12'} - dependencies: - es5-ext: 0.10.64 - type: 2.7.3 - dev: false - - /danmu.js@1.1.13: - resolution: {integrity: sha512-knFd0/cB2HA4FFWiA7eB2suc5vCvoHdqio33FyyCSfP7C+1A+zQcTvnvwfxaZhrxsGj4qaQI2I8XiTqedRaVmg==} - dependencies: - event-emitter: 0.3.5 - dev: false - /dayjs@1.11.13: resolution: {integrity: sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==} dev: false @@ -2190,10 +2183,6 @@ packages: engines: {node: '>=0.4.0'} dev: false - /delegate@3.2.0: - resolution: {integrity: sha512-IofjkYBZaZivn0V8nnsMJGBr4jVLxHDheKSW88PyxS5QC4Vo9ZbZVvhzlSxY87fVq3STR6r+4cGepyHkcWOQSw==} - dev: false - /destr@2.0.3: resolution: {integrity: sha512-2N3BOUU4gYMpTP24s5rF5iP7BDr7uNTCs4ozw3kf/eKfvWSIu93GEBi5m427YoyJoeOzQ5smuu4nNAPGb8idSQ==} dev: true @@ -2202,10 +2191,6 @@ packages: resolution: {integrity: sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w==} dev: false - /downloadjs@1.4.7: - resolution: {integrity: sha512-LN1gO7+u9xjU5oEScGFKvXhYf7Y/empUIIEAGBs1LzUq/rg5duiDrkuH5A2lQGd5jfMOb9X9usDa2oVXwJ0U/Q==} - dev: false - /duplexer@0.1.2: resolution: {integrity: sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==} dev: true @@ -2247,31 +2232,8 @@ packages: resolution: {integrity: sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==} dev: true - /es5-ext@0.10.64: - resolution: {integrity: sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==} - engines: {node: '>=0.10'} - requiresBuild: true - dependencies: - es6-iterator: 2.0.3 - es6-symbol: 3.1.4 - esniff: 2.0.1 - next-tick: 1.1.0 - dev: false - - /es6-iterator@2.0.3: - resolution: {integrity: sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - es6-symbol: 3.1.4 - dev: false - - /es6-symbol@3.1.4: - resolution: {integrity: sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==} - engines: {node: '>=0.12'} - dependencies: - d: 1.0.2 - ext: 1.7.0 + /es6-promise@4.2.8: + resolution: {integrity: sha512-HJDGx5daxeIvxdBxvG2cb9g4tEvwIk3i8+nhX0yGrYmZUzbkdg8QbDevheDB8gd0//uPj4c1EQua8Q+MViT0/w==} dev: false /esbuild@0.23.1: @@ -2444,16 +2406,6 @@ packages: - supports-color dev: true - /esniff@2.0.1: - resolution: {integrity: sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==} - engines: {node: '>=0.10'} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - event-emitter: 0.3.5 - type: 2.7.3 - dev: false - /espree@10.3.0: resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -2499,17 +2451,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /event-emitter@0.3.5: - resolution: {integrity: sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==} - dependencies: - d: 1.0.2 - es5-ext: 0.10.64 - dev: false - - /eventemitter3@4.0.7: - resolution: {integrity: sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==} - dev: false - /execa@9.5.2: resolution: {integrity: sha512-EHlpxMCpHWSAh1dgS6bVeoLAXGnJNdR93aabr4QCGbzOM73o5XmRfM/e5FUqsw3aagP8S8XEWUWFAxnRBnAF0Q==} engines: {node: ^18.19.0 || >=20.5.0} @@ -2528,12 +2469,6 @@ packages: yoctocolors: 2.1.1 dev: true - /ext@1.7.0: - resolution: {integrity: sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==} - dependencies: - type: 2.7.3 - dev: false - /fast-deep-equal@3.1.3: resolution: {integrity: sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==} dev: true @@ -2615,6 +2550,13 @@ packages: resolution: {integrity: sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==} dev: true + /flv.js@1.6.2: + resolution: {integrity: sha512-xre4gUbX1MPtgQRKj2pxJENp/RnaHaxYvy3YToVVCrSmAWUu85b9mug6pTXF6zakUjNP2lFWZ1rkSX7gxhB/2A==} + dependencies: + es6-promise: 4.2.8 + webworkify-webpack: 2.1.5 + dev: false + /follow-redirects@1.15.9: resolution: {integrity: sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==} engines: {node: '>=4.0'} @@ -2737,6 +2679,10 @@ packages: hasBin: true dev: true + /hls.js@1.5.18: + resolution: {integrity: sha512-znxR+2jecWluu/0KOBqUcvVyAB5tLff10vjMGrpAlz1eFY+ZhF1bY3r82V+Bk7WJdk03iTjtja9KFFz5BrqjSA==} + dev: false + /hookable@5.5.3: resolution: {integrity: sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==} dev: true @@ -2919,6 +2865,11 @@ packages: json-buffer: 3.0.1 dev: true + /kind-of@6.0.3: + resolution: {integrity: sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==} + engines: {node: '>=0.10.0'} + dev: false + /kolorist@1.8.0: resolution: {integrity: sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==} dev: true @@ -3115,10 +3066,6 @@ packages: engines: {node: '>=18'} dev: false - /next-tick@1.1.0: - resolution: {integrity: sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==} - dev: false - /node-fetch-native@1.6.4: resolution: {integrity: sha512-IhOigYzAKHd244OC0JIMIUrjzctirCmPkaIfhDeGcEETWof5zKYUW7e7MYvChGWh/4CJeXEgsRyGzuF334rOOQ==} dev: true @@ -3188,6 +3135,12 @@ packages: is-wsl: 3.1.0 dev: true + /option-validator@2.0.6: + resolution: {integrity: sha512-tmZDan2LRIRQyhUGvkff68/O0R8UmF+Btmiiz0SmSw2ng3CfPZB9wJlIjHpe/MKUZqyIZkVIXCrwr1tIN+0Dzg==} + dependencies: + kind-of: 6.0.3 + dev: false + /optionator@0.9.4: resolution: {integrity: sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==} engines: {node: '>= 0.8.0'} @@ -3578,10 +3531,6 @@ packages: engines: {node: '>=10'} dev: true - /type@2.7.3: - resolution: {integrity: sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==} - dev: false - /typescript-eslint@8.18.1(eslint@9.17.0)(typescript@5.6.3): resolution: {integrity: sha512-Mlaw6yxuaDEPQvb/2Qwu3/TfgeBHy9iTJ3mTwe7OvpPmF6KPQjVOfGyEJpPv6Ez2C34OODChhXrzYw/9phI0MQ==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -3940,6 +3889,10 @@ packages: '@vue/shared': 3.5.13 typescript: 5.6.3 + /webworkify-webpack@2.1.5: + resolution: {integrity: sha512-2akF8FIyUvbiBBdD+RoHpoTbHMQF2HwjcxfDvgztAX5YwbZNyrtfUMgvfgFVsgDhDPVTlkbb5vyasqDHfIDPQw==} + dev: false + /which@2.0.2: resolution: {integrity: sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==} engines: {node: '>= 8'} @@ -3961,28 +3914,6 @@ packages: engines: {node: '>=0.10.0'} dev: true - /xgplayer-subtitles@3.0.20(core-js@3.39.0): - resolution: {integrity: sha512-I1bjsIY+aKOrhYQspLdneOkYg+Vf4cJVGPnDSFnNebnxXl9Mhz5SEpWGzYizMYxL9UvsQ9pgjeEY0o4hkwM+kQ==} - peerDependencies: - core-js: '>=3.12.1' - dependencies: - core-js: 3.39.0 - eventemitter3: 4.0.7 - dev: false - - /xgplayer@3.0.20(core-js@3.39.0): - resolution: {integrity: sha512-UNKZJRyODOZGdka83ao8fI18xdhzOV8qG4aNEOOkuOQbXFXfXsJMr/dazRHFP+uXmTqiCXr568euee3ch7CS7g==} - peerDependencies: - core-js: '>=3.12.1' - dependencies: - core-js: 3.39.0 - danmu.js: 1.1.13 - delegate: 3.2.0 - downloadjs: 1.4.7 - eventemitter3: 4.0.7 - xgplayer-subtitles: 3.0.20(core-js@3.39.0) - dev: false - /xml-name-validator@4.0.0: resolution: {integrity: sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==} engines: {node: '>=12'} diff --git a/src/api/alist.ts b/src/api/alist.ts index 594b83c..6c42c88 100644 --- a/src/api/alist.ts +++ b/src/api/alist.ts @@ -58,6 +58,20 @@ export const getFileInfo = async (path: string) => { } } +export const getOtherVideoPreview = async (path: string) => { + try { + const response = await alistApi.post('/api/fs/other', { + path, + method: 'video_preview', + password: '' + }) + return response.data + } catch (error) { + console.error('获取文件信息失败:', error) + throw error + } +} + // 获取下载链接 export const getDownloadUrl = async (path: string) => { try { diff --git a/src/components/VideoPlayer.vue b/src/components/VideoPlayer.vue index 87f8af5..3926129 100644 --- a/src/components/VideoPlayer.vue +++ b/src/components/VideoPlayer.vue @@ -4,15 +4,15 @@