feat: 视频播放插件添加了一个极其简陋的字幕

This commit is contained in:
539943419 committed 2024-08-27 20:42:53 +08:00
1 parent 632a562348
commit f578072997
4 files changed
+135 -22

No files matched your search

+2 -1
View File
@@ -16,7 +16,8 @@
"naive-ui": "^2.39.0",
"sass": "^1.77.8",
"vue": "^3.4.35",
"xgplayer": "^3.0.20"
"xgplayer": "^3.0.20",
"xgplayer-subtitles": "^3.0.20"
},
"devDependencies": {
"@types/lodash": "^4.17.7",
+3
View File
@@ -29,6 +29,9 @@ importers:
xgplayer:
specifier: ^3.0.20
version: 3.0.20(core-js@3.38.1)
xgplayer-subtitles:
specifier: ^3.0.20
version: 3.0.20(core-js@3.38.1)
devDependencies:
'@types/lodash':
specifier: ^4.17.7
+8 -1
View File
@@ -17,6 +17,13 @@ export default function init() {
if (vFiles.length === 0) {
return false;
}
return vFiles.length === 1 && vFiles[0].name.endsWith("mp4");
for(let i of vFiles) {
for(let s of ['mp4', 'm3u8', 'hls']) {
if(i.name.endsWith(s)) {
return true
}
}
}
return false
});
}
+122 -20
View File
@@ -11,35 +11,68 @@
import { VirtualFile } from '@/class/VirtualDirectory';
import miaoDropHandler from '@/components/miaoDropHandler.vue';
import { onBeforeUnmount, onMounted, ref } from 'vue';
import useViretualPages from '@/hooks/useVirtualPages';
// import useViretualPages from '@/hooks/useVirtualPages';
import XGPlayer from 'xgplayer'
import '@/style/xgplayer.scss'
import TextTrack from 'xgplayer/es/plugins/track'
import 'xgplayer/es/plugins/track/index.css'
import axios from 'axios';
import config from '@/config';
const props = defineProps<{
id: number
}>()
// const props = defineProps<{
// id: number
// }>()
const currentFiles = defineModel<VirtualFile[]>('currentFiles', {
required: true
})
const views = useViretualPages()
const view = views.getView(props.id)
// const views = useViretualPages()
// const view = views.getView(props.id)
const videoPath = ref<string>('');
// const videoPath = ref<string>('');
const xgPlayer = ref()
let _player: XGPlayer
const setVideo = (() => {
return (url: string) => {
if (_player) {
_player.src = url
} else {
const { setVideo } = (() => {
return {
setVideo: async (videoVFile: VirtualFile, vttVFiles?: VirtualFile[]) => {
_player && _player.destroy()
const _list = []
if (vttVFiles) {
for (let i of vttVFiles) {
if (i.name.endsWith('srt')) {
const response = await axios.get(i.url)
console.log(srtToVtt(response.data))
const url = setUrl(new Blob([srtToVtt(response.data)]))
_list.push({
id: i.name,
url,
language: 'zh-cn',
text: i.name,
default: i === vttVFiles[0]
})
} else {
_list.push({
id: i.name,
url: i.url,
language: 'zh-cn',
text: i.name,
default: i === vttVFiles[0]
})
}
}
}
const texttrack = {
list: _list
}
_player = new XGPlayer({
plugins: [TextTrack],
el: xgPlayer.value,
url,
url: videoVFile.url,
width: '100%',
height: '100%',
volume: 1,
fluid: true,
pip: true,
videoFillMode: 'contain',
@@ -56,27 +89,96 @@ const setVideo = (() => {
playNext: {
urlList: [
],
}
},
texttrack,
})
}
}
})()
const { setUrl, destroyUrl } = (() => {
const urlList: string[] = []
return {
setUrl(blob: Blob) {
const url = URL.createObjectURL(blob)
urlList.push(url)
return url
},
destroyUrl() {
for (const url of urlList) {
URL.revokeObjectURL(url)
}
}
}
})()
const handleDropVFiles = (files: VirtualFile[]) => {
console.log(files)
view && (view.currentFiles[0] = files[0])
videoPath.value = files[0].url;
setVideo(videoPath.value)
setVideo(findVideo(files), findTextTrack(files))
};
function srtToVtt(srt: string) {
// 将 SRT 字幕按行分割
const lines = srt.split('\n');
let vtt = 'WEBVTT\n\n'; // VTT 文件的开头
let index = 0;
while (index < lines.length) {
// 跳过空行
if (lines[index].trim() === '') {
index++;
continue;
}
// SRT 中的序号
const sequenceNumber = lines[index].trim();
index++;
// 时间戳
const timeLine = lines[index].trim().replace(/,/g, '.'); // 将逗号替换为点
index++;
// 字幕文本
let text = '';
while (index < lines.length && lines[index].trim() !== '') {
text += lines[index].trim() + '\n';
index++;
}
// 添加到 VTT 字幕中
vtt += `${timeLine}\n${text.trim()}\n\n`;
}
return vtt;
}
const findVideo = (vFiles: VirtualFile[]) => vFiles.filter(v => {
for (let s of ['mp4', 'm3u8', 'hls']) {
if (v.name.endsWith(s)) {
return true
}
}
return false
})[0]
const findTextTrack = (vFiles: VirtualFile[]) => vFiles.filter(v => {
for (let s of ['vtt', 'srt']) {
if (v.name.endsWith(s)) {
return true
}
}
return false
})
onMounted(() => {
if(currentFiles.value.length) {
setVideo(currentFiles.value[0].url)
if (currentFiles.value.length) {
setVideo(findVideo(currentFiles.value), findTextTrack(currentFiles.value))
}
});
onBeforeUnmount(() => {
_player.destroy()
destroyUrl()
})
</script>