feat: 用aplayer随便做了一个音乐插件

This commit is contained in:
539943419 committed 2024-09-27 00:42:15 +08:00
1 parent 5173b28ec5
commit 4b5b7956c7
8 files changed
+186 -47

No files matched your search

+1
View File
@@ -25,6 +25,7 @@
"@codemirror/lang-yaml": "^6.1.1", "@codemirror/lang-yaml": "^6.1.1",
"@vicons/ionicons5": "^0.12.0", "@vicons/ionicons5": "^0.12.0",
"aes-js": "^3.1.2", "aes-js": "^3.1.2",
"aplayer": "^1.10.1",
"axios": "^1.7.3", "axios": "^1.7.3",
"codemirror": "^6.0.1", "codemirror": "^6.0.1",
"copy-to-clipboard": "^3.3.3", "copy-to-clipboard": "^3.3.3",
+27
View File
@@ -47,6 +47,9 @@ importers:
aes-js: aes-js:
specifier: ^3.1.2 specifier: ^3.1.2
version: 3.1.2 version: 3.1.2
aplayer:
specifier: ^1.10.1
version: 1.10.1
axios: axios:
specifier: ^1.7.3 specifier: ^1.7.3
version: 1.7.3 version: 1.7.3
@@ -606,6 +609,9 @@ packages:
resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==} resolution: {integrity: sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==}
engines: {node: '>= 8'} engines: {node: '>= 8'}
aplayer@1.10.1:
resolution: {integrity: sha512-HAfyxgCUTLAqtYlxzzK9Fyqg6y+kZ9CqT1WfeWE8FSzwspT6oBqWOZHANPHF3RGTtC33IsyEgrfthPDzU5r9kQ==}
aproba@2.0.0: aproba@2.0.0:
resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==} resolution: {integrity: sha512-lYe4Gx7QT+MKGbDsA+Z+he/Wtef0BiwDOlK/XkBrdfsh9J/jPPXbX0tE9x9cl27Tmu5gg3QUbUrQYa/y+KOHPQ==}
@@ -629,6 +635,9 @@ packages:
balanced-match@1.0.2: balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
balloon-css@0.5.2:
resolution: {integrity: sha512-zheJpzwyNrG4t39vusA67v3BYg1HTVXOF8cErPEHzWK88PEOFwgo6Ea9VHOgOWNMgeuOtFVtB73NE2NWl9uDyQ==}
binary-extensions@2.3.0: binary-extensions@2.3.0:
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
engines: {node: '>=8'} engines: {node: '>=8'}
@@ -1019,6 +1028,9 @@ packages:
resolution: {integrity: sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==} resolution: {integrity: sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==}
engines: {node: ^10 || ^12 || >=14} engines: {node: ^10 || ^12 || >=14}
promise-polyfill@7.1.0:
resolution: {integrity: sha512-P6NJ2wU/8fac44ENORsuqT8TiolKGB2u0fEClPtXezn7w5cmLIjM/7mhPlTebke2EPr6tmqZbXvnX0TxwykGrg==}
proxy-from-env@1.1.0: proxy-from-env@1.1.0:
resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==} resolution: {integrity: sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==}
@@ -1079,6 +1091,9 @@ packages:
simple-get@3.1.1: simple-get@3.1.1:
resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==} resolution: {integrity: sha512-CQ5LTKGfCpvE1K0n2us+kuMPbk/q0EKl82s4aheV9oXjFEz6W/Y7oQFVJuU6QG77hRT4Ghb5RURteF5vnWjupA==}
smoothscroll@0.4.0:
resolution: {integrity: sha512-sggQ3U2Un38b3+q/j1P4Y4fCboCtoUIaBYoge+Lb6Xg1H8RTIif/hugVr+ErMtIDpvBbhQfTjtiTeYAfbw1ZGQ==}
source-map-js@1.2.0: source-map-js@1.2.0:
resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==} resolution: {integrity: sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==}
engines: {node: '>=0.10.0'} engines: {node: '>=0.10.0'}
@@ -1793,6 +1808,12 @@ snapshots:
normalize-path: 3.0.0 normalize-path: 3.0.0
picomatch: 2.3.1 picomatch: 2.3.1
aplayer@1.10.1:
dependencies:
balloon-css: 0.5.2
promise-polyfill: 7.1.0
smoothscroll: 0.4.0
aproba@2.0.0: aproba@2.0.0:
optional: true optional: true
@@ -1818,6 +1839,8 @@ snapshots:
balanced-match@1.0.2: {} balanced-match@1.0.2: {}
balloon-css@0.5.2: {}
binary-extensions@2.3.0: {} binary-extensions@2.3.0: {}
brace-expansion@1.1.11: brace-expansion@1.1.11:
@@ -2271,6 +2294,8 @@ snapshots:
picocolors: 1.0.1 picocolors: 1.0.1
source-map-js: 1.2.0 source-map-js: 1.2.0
promise-polyfill@7.1.0: {}
proxy-from-env@1.1.0: {} proxy-from-env@1.1.0: {}
punycode.js@2.3.1: {} punycode.js@2.3.1: {}
@@ -2347,6 +2372,8 @@ snapshots:
simple-concat: 1.0.1 simple-concat: 1.0.1
optional: true optional: true
smoothscroll@0.4.0: {}
source-map-js@1.2.0: {} source-map-js@1.2.0: {}
string-width@4.2.3: string-width@4.2.3:
+33
View File
@@ -0,0 +1,33 @@
import { registerComponentOption } from '@/class/PluginCenter'
import { PluginExportType } from '@/types/type'
import Disc from '@vicons/ionicons5/es/Disc'
const pluginConfig: registerComponentOption = {
key: 'miaoMusicPlayer',
name: '音乐',
icon: Disc,
getComponent: async () =>
(await import('./miaoMusicPlayerDemo.vue')).default,
filter: (vDirs, vFiles) => {
if (vDirs.length !== 0) {
return false
}
if (vFiles.length === 0) {
return false
}
for (let i of vFiles) {
for (let s of ['mp3']) {
if (i.name.endsWith(s)) {
return true
}
}
}
return vFiles[0].name.endsWith('?')
},
disable: false
}
export default pluginConfig
export const type = PluginExportType.component
@@ -0,0 +1,73 @@
<template>
<miao-drop-handler @on-virtual-files="handleDropVFiles">
<div class="miaoMusic-container">
<div ref="aplayer" />
</div>
</miao-drop-handler>
</template>
<script setup lang="ts">
import miaoDropHandler from '@/components/miaoDropHandler.vue'
import { VirtualFile } from '@/class/VirtualDirectory';
import { computed, onMounted, onUnmounted, ref } from 'vue';
import 'APlayer/dist/APlayer.min.css';
// @ts-ignore
import APlayer from 'APlayer';
import config from '@/config';
const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
required: true
});
const MusicList = computed(() => currentFiles.value.map(v => ({
url: `${config.baseUrl}${v.url}`,
name: v.name,
artist: '???',
})));
const handleDropVFiles = (files: VirtualFile[]) => {
currentFiles.value = [...currentFiles.value, ...files];
};
const aplayer = ref<any>(null);
let ap: any
onMounted(() => {
currentFiles.value = [...currentFiles.value.reverse()]
const aplayerOption = {
container: aplayer.value,
audio: MusicList.value,
autoplay: true,
}
ap = new APlayer(aplayerOption);
});
onUnmounted(() => {
ap.destroy()
})
</script>
<style scoped lang="scss">
.miaoMusic-container {
width: 100%;
height: 100%;
}
</style>
<style lang="scss">
.aplayer {
height: calc(100% - 10px);
display: flex;
flex-direction: column;
// .aplayer-list {
// max-height: none !important;
// height: fit-content;
// min-height: 0;
// ol {
// max-height: none !important;
// height: fit-content;
// }
// }
}
</style>
+2 -2
View File
@@ -1,5 +1,5 @@
<template> <template>
<div class="miaoCrypto-container"></div> <div class="template-container"></div>
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
@@ -12,7 +12,7 @@
</script> </script>
<style scoped lang="scss"> <style scoped lang="scss">
.miaoCrypto-container { .template-container {
width: 100%; width: 100%;
height: 100%; height: 100%;
} }
+49 -39
View File
@@ -14,36 +14,70 @@ import XGPlayer from 'xgplayer'
import '@/style/xgplayer.scss' import '@/style/xgplayer.scss'
import TextTrack from 'xgplayer/es/plugins/track' import TextTrack from 'xgplayer/es/plugins/track'
import 'xgplayer/es/plugins/track/index.css' import 'xgplayer/es/plugins/track/index.css'
import axios from 'axios'
import { uniq } from 'lodash'
import lockScreen from './playerPlugin/lockScreen/lockScreen' import lockScreen from './playerPlugin/lockScreen/lockScreen'
import xgplayerVueApp from './src/XGPlayerVuePluginRoot.vue' import xgplayerVueApp from './src/XGPlayerVuePluginRoot.vue'
import useXGPlayerVueFrame from './playerPlugin/xgplayer-vue-frame/xgplayer-vue-frame' import useXGPlayerVueFrame from './playerPlugin/xgplayer-vue-frame/xgplayer-vue-frame'
import axios from 'axios'
import { uniq } from 'lodash'
const currentFiles = defineModel<VirtualFile[]>('currentFiles', { const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
required: true required: true
}) })
// const views = useVirtualPages()
// const view = views.getView(props.id)
// const videoPath = ref<string>('');
const xgPlayer = ref() const xgPlayer = ref()
let _player: XGPlayer let _player: XGPlayer
const { setVideo } = (() => { const { setVideo } = (() => {
const initPlayer = (videos: VirtualFile[], texttrack: {
list: {
id: number; url: string
text: string
}[]
}) => {
const videoVFile = videos.shift() as VirtualFile
_player && _player.destroy()
_player = new XGPlayer({
plugins: [
TextTrack,
lockScreen,
useXGPlayerVueFrame(xgplayerVueApp),
],
el: xgPlayer.value,
url: videoVFile.url,
width: '100%',
height: '100%',
volume: 1,
// loop: true,
// pip: true,
videoFillMode: 'contain',
autoplay: true,
download: true,
screenShot: {
saveImg: true,
quality: 1,
type: 'image/png',
format: '.png'
},
lang: 'zh-cn',
playbackRate: [0.1, 0.3, 0.5, 0.75, 1, 1.5, 2, 3, 5, 10],
playNext: {
urlList: videos.map(v => v.url)
},
texttrack,
ignores: [videos.length === 0 ? 'playNext' : undefined].filter(v => v) as string[]
})
}
return { return {
setVideo: async ( setVideo: async (
videoVFiles: VirtualFile[], videoVFiles: VirtualFile[],
textTrackFiles?: VirtualFile[] textTrackFiles?: VirtualFile[]
) => { ) => {
// 天哪什么精神状态会写出这种代码
textTrackFiles && textTrackFiles &&
textTrackFiles.push(...findTextTrack(currentFiles.value)) textTrackFiles.push(...findTextTrack(currentFiles.value))
textTrackFiles = uniq(textTrackFiles) textTrackFiles = uniq(textTrackFiles)
currentFiles.value = [...currentFiles.value, ...videoVFiles, ...(textTrackFiles ?? [])] currentFiles.value = uniq([...currentFiles.value, ...videoVFiles, ...(textTrackFiles ?? [])])
const videos = findVideo(currentFiles.value) const videos = findVideo(uniq([...currentFiles.value, ...videoVFiles]))
const videoVFile = videos.shift() as VirtualFile
const _list = [] const _list = []
if (textTrackFiles) { if (textTrackFiles) {
for (let i of textTrackFiles) { for (let i of textTrackFiles) {
@@ -88,32 +122,7 @@ const { setVideo } = (() => {
const texttrack = { const texttrack = {
list: _list list: _list
} }
_player && _player.destroy() initPlayer([...videos], texttrack)
_player = new XGPlayer({
plugins: [TextTrack, lockScreen, useXGPlayerVueFrame(xgplayerVueApp)],
el: xgPlayer.value,
url: videoVFile.url,
width: '100%',
height: '100%',
volume: 1,
loop: true,
// pip: true,
videoFillMode: 'contain',
autoplay: true,
download: true,
screenShot: {
saveImg: true,
quality: 1,
type: 'image/png',
format: '.png'
},
lang: 'zh-cn',
playbackRate: [0.1, 0.3, 0.5, 0.75, 1, 1.5, 2, 3, 5, 10],
playNext: {
urlList: videos.map(v=>v.url)
},
texttrack
})
} }
} }
})() })()
@@ -135,7 +144,7 @@ const { setUrl, destroyUrl } = (() => {
})() })()
const handleDropVFiles = (files: VirtualFile[]) => { const handleDropVFiles = (files: VirtualFile[]) => {
setVideo(findVideo(files), findTextTrack(files)) setVideo(findVideo(files.reverse()), findTextTrack(files))
} }
function srtToVtt(srt: string) { function srtToVtt(srt: string) {
@@ -282,14 +291,14 @@ function ssaToVtt(ssaContent: string): string {
} }
const findVideo = (vFiles: VirtualFile[]) => const findVideo = (vFiles: VirtualFile[]) =>
vFiles.filter((v) => { uniq(vFiles.filter((v) => {
for (let s of ['mp4', 'mp3']) { for (let s of ['mp4', 'mp3']) {
if (v.name.endsWith(s)) { if (v.name.endsWith(s)) {
return true return true
} }
} }
return false return false
}) }))
const findTextTrack = (vFiles: VirtualFile[]) => const findTextTrack = (vFiles: VirtualFile[]) =>
vFiles.filter((v) => { vFiles.filter((v) => {
@@ -303,6 +312,7 @@ const findTextTrack = (vFiles: VirtualFile[]) =>
onMounted(() => { onMounted(() => {
if (currentFiles.value.length) { if (currentFiles.value.length) {
currentFiles.value.reverse()
setVideo( setVideo(
findVideo(currentFiles.value), findVideo(currentFiles.value),
findTextTrack(currentFiles.value) findTextTrack(currentFiles.value)
@@ -5,7 +5,7 @@
</template> </template>
<script setup lang="ts"> <script setup lang="ts">
import { onMounted, Component, toRaw } from "vue"; import { Component, toRaw } from "vue";
import Player from "xgplayer/es/player"; import Player from "xgplayer/es/player";
import { pick } from "lodash"; import { pick } from "lodash";
const props = defineProps({ const props = defineProps({
@@ -23,10 +23,6 @@ const props = defineProps({
} }
}) })
onMounted(() => {
console.log(props)
})
</script> </script>
<style lang="scss" scoped> <style lang="scss" scoped>
@@ -16,7 +16,6 @@ const useXGPlayerVueFrame = (App: Component) => {
} }
afterCreate() { afterCreate() {
console.log({fakeApp})
this.createVueFrame(); this.createVueFrame();
} }