提交 1e6c31b8 authored 作者: 王鹏飞's avatar 王鹏飞

feat: 增加视频播放URL和类型的获取功能,优化视频组件

上级 466a9d89
...@@ -17,7 +17,7 @@ const fileExtensionName = $computed(() => { ...@@ -17,7 +17,7 @@ const fileExtensionName = $computed(() => {
}) })
const isOfficeFile = $computed(() => { const isOfficeFile = $computed(() => {
return ['pptx', 'doc', 'docx', 'xls', 'xlsx'].includes(fileExtensionName) return ['ppt', 'pptx', 'doc', 'docx', 'xls', 'xlsx'].includes(fileExtensionName)
}) })
const isVideoFile = $computed(() => { const isVideoFile = $computed(() => {
......
<script setup lang="ts"> <script setup lang="ts">
import { VideoPlay } from '@element-plus/icons-vue' import { VideoPlay } from '@element-plus/icons-vue'
import { createVideoUploader, type VideoUploadItem } from '@/utils/videoUpload' import { createVideoUploader, getUploadedVideoSourceId, type VideoUploadItem } from '@/utils/videoUpload'
interface Props { interface Props {
beforeUpload?: (file: any) => void beforeUpload?: (file: any) => void
...@@ -14,7 +14,7 @@ const emit = defineEmits<{ ...@@ -14,7 +14,7 @@ const emit = defineEmits<{
const { files, uploading, addFile, stopUpload } = createVideoUploader({ const { files, uploading, addFile, stopUpload } = createVideoUploader({
onUploadSucceed(file: VideoUploadItem) { onUploadSucceed(file: VideoUploadItem) {
// 保持与现有调用方兼容的接口 // 保持与现有调用方兼容的接口
emit('success', { file: { name: file.name }, videoId: file.videoId }) emit('success', { file: { name: file.name }, videoId: getUploadedVideoSourceId(file) })
}, },
}) })
...@@ -56,7 +56,7 @@ function addFileToUploader(file: File) { ...@@ -56,7 +56,7 @@ function addFileToUploader(file: File) {
} }
function percentage(value: number) { function percentage(value: number) {
return parseFloat((value ? value * 100 : 0).toFixed(2)) return parseFloat((value || 0).toFixed(2))
} }
</script> </script>
<template> <template>
...@@ -65,7 +65,7 @@ function percentage(value: number) { ...@@ -65,7 +65,7 @@ function percentage(value: number) {
{{ uploading ? '上传中...' : '本地文件' }} {{ uploading ? '上传中...' : '本地文件' }}
<input accept=".mp4" type="file" @change="fileChange" :disabled="uploading" /> <input accept=".mp4" type="file" @change="fileChange" :disabled="uploading" />
</div> </div>
<div class="tips">推荐视频格式:帧率为25fps\输出码率为4M\输出格式为mp4,建议采用格式工厂等工具处理后上传。</div> <div class="tips">支持视频格式:mp4,推荐帧率为25fps、输出码率为4M。</div>
<ul class="upload-video-list" v-for="(item, index) in files" :key="index"> <ul class="upload-video-list" v-for="(item, index) in files" :key="index">
<li> <li>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import type { ContestVideoItem } from '../types' import type { ContestVideoItem } from '../types'
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue' import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
import { getContestVideoPalyInfo } from '../api' import { getContestVideoPalyInfo } from '../api'
import { getVideoPlayUrl, getVideoSourceType } from '@/utils/video'
interface Props { interface Props {
data: ContestVideoItem data: ContestVideoItem
} }
...@@ -13,15 +14,9 @@ function fetchInfo() { ...@@ -13,15 +14,9 @@ function fetchInfo() {
}) })
} }
const playUrl = $computed(() => { const playUrl = $computed(() => {
const definitionUrl = playList.reduce( return getVideoPlayUrl(playList)
(result: any, item: any) => {
result[item.Definition] = item.PlayURL
return result
},
{ SD: '', LD: '', FD: '' }
)
return definitionUrl.SD || definitionUrl.LD || definitionUrl.FD
}) })
const playType = $computed(() => getVideoSourceType(playUrl))
onMounted(() => { onMounted(() => {
fetchInfo() fetchInfo()
}) })
...@@ -30,7 +25,7 @@ onMounted(() => { ...@@ -30,7 +25,7 @@ onMounted(() => {
<template> <template>
<el-dialog title="查阅操作视频"> <el-dialog title="查阅操作视频">
<AppVideoPlayer <AppVideoPlayer
:options="{ fluid: true, sources: [{ src: playUrl, type: 'application/x-mpegURL' }] }" :options="{ fluid: true, sources: [{ src: playUrl, type: playType }] }"
v-if="playUrl"></AppVideoPlayer> v-if="playUrl"></AppVideoPlayer>
</el-dialog> </el-dialog>
</template> </template>
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import type { VideoItem } from '../types' import type { VideoItem } from '../types'
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue' import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
import { getVideo } from '../api' import { getVideo } from '../api'
import { getVideoPlayUrl, getVideoSourceType } from '@/utils/video'
interface Props { interface Props {
id: string id: string
...@@ -19,15 +20,9 @@ function fetchInfo() { ...@@ -19,15 +20,9 @@ function fetchInfo() {
}) })
} }
const playUrl = $computed(() => { const playUrl = $computed(() => {
const definitionUrl = playList.reduce( return getVideoPlayUrl(playList)
(result: any, item: any) => {
result[item.Definition] = item.PlayURL
return result
},
{ SD: '', LD: '', FD: '' }
)
return definitionUrl.SD || definitionUrl.LD || definitionUrl.FD
}) })
const playType = $computed(() => getVideoSourceType(playUrl))
onMounted(() => { onMounted(() => {
fetchInfo() fetchInfo()
}) })
...@@ -48,7 +43,7 @@ onMounted(() => { ...@@ -48,7 +43,7 @@ onMounted(() => {
</el-descriptions> </el-descriptions>
<div style="height: 600px" v-if="playUrl"> <div style="height: 600px" v-if="playUrl">
<AppVideoPlayer <AppVideoPlayer
:options="{ sources: [{ src: playUrl, type: 'application/x-mpegURL' }] }" :options="{ sources: [{ src: playUrl, type: playType }] }"
style="width: 100%; height: 100%"></AppVideoPlayer> style="width: 100%; height: 100%"></AppVideoPlayer>
</div> </div>
</template> </template>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import type { ExperimentVideoType, PlayInfo } from '../types' import type { ExperimentVideoType, PlayInfo } from '../types'
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue' import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
import { getExperimentVideoPlayInfo } from '../api' import { getExperimentVideoPlayInfo } from '../api'
import { getVideoPlayUrl, getVideoSourceType } from '@/utils/video'
// import { useLog } from '@/composables/useLog' // import { useLog } from '@/composables/useLog'
// const log = useLog() // const log = useLog()
...@@ -28,15 +29,9 @@ function fetchInfo() { ...@@ -28,15 +29,9 @@ function fetchInfo() {
}) })
} }
const playUrl = $computed(() => { const playUrl = $computed(() => {
const definitionUrl = playList.reduce( return getVideoPlayUrl(playList)
(result: any, item: any) => {
result[item.Definition] = item.PlayURL
return result
},
{ SD: '', LD: '', FD: '' }
)
return definitionUrl.SD || definitionUrl.LD || definitionUrl.FD
}) })
const playType = $computed(() => getVideoSourceType(playUrl))
onMounted(() => { onMounted(() => {
fetchInfo() fetchInfo()
}) })
...@@ -47,7 +42,7 @@ onMounted(() => { ...@@ -47,7 +42,7 @@ onMounted(() => {
<!-- <img :src="data.cover" /> --> <!-- <img :src="data.cover" /> -->
<div style="height: 200px" v-if="playUrl"> <div style="height: 200px" v-if="playUrl">
<AppVideoPlayer <AppVideoPlayer
:options="{ sources: [{ src: playUrl, type: 'application/x-mpegURL' }] }" :options="{ sources: [{ src: playUrl, type: playType }] }"
style="width: 100%; height: 100%"></AppVideoPlayer> style="width: 100%; height: 100%"></AppVideoPlayer>
</div> </div>
</div> </div>
......
...@@ -2,6 +2,7 @@ ...@@ -2,6 +2,7 @@
import type { ExperimentVideoType, PlayInfo } from '../types' import type { ExperimentVideoType, PlayInfo } from '../types'
import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue' import AppVideoPlayer from '@/components/base/AppVideoPlayer.vue'
import { getExperimentVideoPlayInfo } from '../api' import { getExperimentVideoPlayInfo } from '../api'
import { getVideoPlayUrl, getVideoSourceType } from '@/utils/video'
import { useLog } from '@/composables/useLog' import { useLog } from '@/composables/useLog'
const log = useLog() const log = useLog()
...@@ -29,15 +30,9 @@ function fetchInfo() { ...@@ -29,15 +30,9 @@ function fetchInfo() {
}) })
} }
const playUrl = $computed(() => { const playUrl = $computed(() => {
const definitionUrl = playList.reduce( return getVideoPlayUrl(playList)
(result: any, item: any) => {
result[item.Definition] = item.PlayURL
return result
},
{ SD: '', LD: '', FD: '' }
)
return definitionUrl.SD || definitionUrl.LD || definitionUrl.FD
}) })
const playType = $computed(() => getVideoSourceType(playUrl))
onMounted(() => { onMounted(() => {
fetchInfo() fetchInfo()
}) })
...@@ -48,7 +43,7 @@ onMounted(() => { ...@@ -48,7 +43,7 @@ onMounted(() => {
<!-- <img :src="data.cover" /> --> <!-- <img :src="data.cover" /> -->
<div style="height: 200px" v-if="playUrl"> <div style="height: 200px" v-if="playUrl">
<AppVideoPlayer <AppVideoPlayer
:options="{ sources: [{ src: playUrl, type: 'application/x-mpegURL' }] }" :options="{ sources: [{ src: playUrl, type: playType }] }"
style="width: 100%; height: 100%"></AppVideoPlayer> style="width: 100%; height: 100%"></AppVideoPlayer>
</div> </div>
</div> </div>
......
...@@ -5,9 +5,18 @@ ...@@ -5,9 +5,18 @@
*/ */
import { urls } from './env' import { urls } from './env'
function toBase64(value: string) {
const bytes = new TextEncoder().encode(value)
let binary = ''
bytes.forEach(byte => {
binary += String.fromCharCode(byte)
})
return btoa(binary)
}
export function getOnlinePreviewUrl(url: string): string { export function getOnlinePreviewUrl(url: string): string {
if (import.meta.env.MODE === 'school') { if (import.meta.env.MODE === 'school') {
return `${urls.filePreview}/onlinePreview?url=${encodeURIComponent(btoa(url))}` return `${urls.filePreview}/onlinePreview?url=${encodeURIComponent(toBase64(encodeURI(url)))}`
} }
return `https://view.officeapps.live.com/op/view.aspx?src=${url}` return `https://view.officeapps.live.com/op/view.aspx?src=${url}`
} }
export function getVideoPlayUrl(playInfo?: any) {
if (typeof playInfo === 'string') return playInfo
if (!Array.isArray(playInfo)) return ''
const definitionUrl = playInfo.reduce(
(result: Record<string, string>, item: any) => {
if (item?.Definition && item?.PlayURL) result[item.Definition] = item.PlayURL
return result
},
{ SD: '', LD: '', FD: '' },
)
return definitionUrl.SD || definitionUrl.LD || definitionUrl.FD || playInfo[0]?.PlayURL || ''
}
export function getVideoSourceType(url: string) {
return /\.m3u8(?:[?#]|$)/i.test(url) ? 'application/x-mpegURL' : 'video/mp4'
}
Markdown 格式
0% 或
您添加了 0 人 到此讨论。请谨慎行事。
请先完成此评论的编辑!
请 注册 或者 后发表评论