|
@@ -100,7 +100,7 @@
|
|
|
</div>
|
|
</div>
|
|
|
|
|
|
|
|
<div class="box-2">
|
|
<div class="box-2">
|
|
|
- <!-- 课程标题 autoplay自动播放 @ended="playNextVideo"-->
|
|
|
|
|
|
|
+ <!-- 课程标题 autoplay自动播放 @ended="playNextVideo" @play="checkVideoPermission" :controlsList="[nodownload]"-->
|
|
|
<div class="small-title">
|
|
<div class="small-title">
|
|
|
<span>{{ course.courseName }}</span>
|
|
<span>{{ course.courseName }}</span>
|
|
|
</div>
|
|
</div>
|
|
@@ -108,10 +108,8 @@
|
|
|
<Vue3VideoPlay
|
|
<Vue3VideoPlay
|
|
|
class="full-box-video"
|
|
class="full-box-video"
|
|
|
:src="course.courseVideoPath"
|
|
:src="course.courseVideoPath"
|
|
|
- :controlsList="[nodownload]"
|
|
|
|
|
:controls="false"
|
|
:controls="false"
|
|
|
@timeupdate="handleTimeUpdate"
|
|
@timeupdate="handleTimeUpdate"
|
|
|
- @play="checkVideoPermission"
|
|
|
|
|
@seeked="handleSeeked"
|
|
@seeked="handleSeeked"
|
|
|
@ended="handleVideoEnded"
|
|
@ended="handleVideoEnded"
|
|
|
ref="videoRef"
|
|
ref="videoRef"
|
|
@@ -274,17 +272,14 @@ import { ref, onMounted, onUnmounted, onBeforeUnmount, computed } from 'vue'
|
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
import { useRoute, useRouter } from 'vue-router'
|
|
|
// import videojs from 'video.js'
|
|
// import videojs from 'video.js'
|
|
|
// import 'video.js/dist/video-js.css'
|
|
// import 'video.js/dist/video-js.css'
|
|
|
-// import '@videojs/http-streaming' // 支持HLS分片
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
-
|
|
|
|
|
|
|
+import '@videojs/http-streaming' // 支持HLS分片
|
|
|
import "vue3-video-play/dist/style.css";
|
|
import "vue3-video-play/dist/style.css";
|
|
|
import { videoPlay as Vue3VideoPlay } from "vue3-video-play";
|
|
import { videoPlay as Vue3VideoPlay } from "vue3-video-play";
|
|
|
// 导入hls.js以支持m3u8格式
|
|
// 导入hls.js以支持m3u8格式
|
|
|
import Hls from 'hls.js'
|
|
import Hls from 'hls.js'
|
|
|
|
|
|
|
|
const videoPlayer = ref(null)
|
|
const videoPlayer = ref(null)
|
|
|
-// let player = null
|
|
|
|
|
|
|
+let player = null
|
|
|
|
|
|
|
|
import { Expand, Fold, Memo } from '@element-plus/icons-vue'
|
|
import { Expand, Fold, Memo } from '@element-plus/icons-vue'
|
|
|
import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
|
|
import { Search, ArrowLeftBold } from '@element-plus/icons-vue'
|
|
@@ -428,13 +423,25 @@ onMounted(async () => {
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+
|
|
|
|
|
+
|
|
|
const title = router.currentRoute.value.query.typeName
|
|
const title = router.currentRoute.value.query.typeName
|
|
|
if (title) {
|
|
if (title) {
|
|
|
boxIconTitle.value = String(title)
|
|
boxIconTitle.value = String(title)
|
|
|
}
|
|
}
|
|
|
- // 在视频元素上添加时间更新事件监听
|
|
|
|
|
- if (videoRef.value) {
|
|
|
|
|
- videoRef.value.addEventListener('timeupdate', handleTimeUpdate)
|
|
|
|
|
|
|
+ // // 在视频元素上添加时间更新事件监听
|
|
|
|
|
+ // if (videoRef.value) {
|
|
|
|
|
+ // videoRef.value.addEventListener('timeupdate', handleTimeUpdate)
|
|
|
|
|
+ // }
|
|
|
|
|
+})
|
|
|
|
|
+ onBeforeUnmount(() => {
|
|
|
|
|
+ if (player) {
|
|
|
|
|
+ player.dispose()
|
|
|
|
|
+ player = null
|
|
|
|
|
+ }
|
|
|
|
|
+ if (hlsRef.value) {
|
|
|
|
|
+ hlsRef.value.destroy()
|
|
|
|
|
+ hlsRef.value = null
|
|
|
}
|
|
}
|
|
|
})
|
|
})
|
|
|
|
|
|
|
@@ -514,14 +521,11 @@ const playNextVideo = () => {
|
|
|
if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
|
|
if (currentIndexInList !== -1 && currentIndexInList < allIndices.length - 1) {
|
|
|
const nextIndex = allIndices[currentIndexInList + 1]
|
|
const nextIndex = allIndices[currentIndexInList + 1]
|
|
|
handleSelect(nextIndex)
|
|
handleSelect(nextIndex)
|
|
|
- // 切换视频后自动播放
|
|
|
|
|
- if (videoRef.value) {
|
|
|
|
|
- videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
|
|
|
|
|
- once: true
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 切换视频后自动播放
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ tryPlayVideo()
|
|
|
|
|
+ }, 500)
|
|
|
}
|
|
}
|
|
|
-
|
|
|
|
|
// 重置
|
|
// 重置
|
|
|
pausedIndices.value = []
|
|
pausedIndices.value = []
|
|
|
prompt.value = ''
|
|
prompt.value = ''
|
|
@@ -539,19 +543,25 @@ const playPreviousVideo = () => {
|
|
|
if (currentIndexInList > 0) {
|
|
if (currentIndexInList > 0) {
|
|
|
const previousIndex = allIndices[currentIndexInList - 1]
|
|
const previousIndex = allIndices[currentIndexInList - 1]
|
|
|
handleSelect(previousIndex)
|
|
handleSelect(previousIndex)
|
|
|
- // 切换视频后自动播放
|
|
|
|
|
- if (videoRef.value) {
|
|
|
|
|
- videoRef.value.addEventListener('loadedmetadata', tryPlayVideo, {
|
|
|
|
|
- once: true
|
|
|
|
|
- })
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ // 切换视频后自动播放
|
|
|
|
|
+ setTimeout(() => {
|
|
|
|
|
+ tryPlayVideo()
|
|
|
|
|
+ }, 500)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
// 尝试播放视频,处理浏览器自动播放限制
|
|
// 尝试播放视频,处理浏览器自动播放限制
|
|
|
const tryPlayVideo = () => {
|
|
const tryPlayVideo = () => {
|
|
|
- //测试账号禁用视频
|
|
|
|
|
|
|
+ // 测试账号禁用视频
|
|
|
if (disableVideo()) return
|
|
if (disableVideo()) return
|
|
|
|
|
+ // 判断视频格式是否为m3u8
|
|
|
|
|
+ const isM3u8 = course.value.courseVideoPath && course.value.courseVideoPath.endsWith('.m3u8')
|
|
|
|
|
+
|
|
|
|
|
+ // 确保videoRef存在
|
|
|
|
|
+ if (!videoRef.value) {
|
|
|
|
|
+ console.error('视频元素未找到')
|
|
|
|
|
+ return
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
const playPromise = videoRef.value.play()
|
|
const playPromise = videoRef.value.play()
|
|
|
if (playPromise !== undefined) {
|
|
if (playPromise !== undefined) {
|
|
@@ -559,35 +569,39 @@ const tryPlayVideo = () => {
|
|
|
console.error('视频播放失败,可能是浏览器自动播放限制:', error)
|
|
console.error('视频播放失败,可能是浏览器自动播放限制:', error)
|
|
|
})
|
|
})
|
|
|
}
|
|
}
|
|
|
- // 判断视频格式是否为m3u8
|
|
|
|
|
- const isM3u8 = course.value.courseVideoPath && course.value.courseVideoPath.endsWith('.m3u8')
|
|
|
|
|
- player = videojs(videoPlayer.value, {
|
|
|
|
|
- controls: true,
|
|
|
|
|
- sources: [
|
|
|
|
|
- {
|
|
|
|
|
- src: course.value.courseVideoPath,
|
|
|
|
|
- type: isM3u8 ? 'application/x-mpegURL' : 'video/mp4'
|
|
|
|
|
- }
|
|
|
|
|
- ],
|
|
|
|
|
- preload: 'metadata' // 仅加载元数据,避免预加载整个文件
|
|
|
|
|
- })
|
|
|
|
|
- // 如果是m3u8格式,启用HLS支持
|
|
|
|
|
- if (isM3u8 && !hlsRef.value) {
|
|
|
|
|
- // 检查是否已加载hls.js插件
|
|
|
|
|
- if (videojs.getPlugin('hls')) {
|
|
|
|
|
- hlsRef.value = player.hls()
|
|
|
|
|
- // 可以在这里添加额外的HLS配置
|
|
|
|
|
- } else {
|
|
|
|
|
- console.warn('video.js HLS插件未加载,可能无法正常播放m3u8格式视频')
|
|
|
|
|
|
|
+
|
|
|
|
|
+ // 初始化video.js播放器
|
|
|
|
|
+ if (videoPlayer.value) {
|
|
|
|
|
+ // 销毁旧的播放器实例(如果存在)
|
|
|
|
|
+ if (player) {
|
|
|
|
|
+ player.dispose()
|
|
|
}
|
|
}
|
|
|
- }
|
|
|
|
|
-}
|
|
|
|
|
|
|
|
|
|
-// 检查视频播放权限
|
|
|
|
|
-const checkVideoPermission = () => {
|
|
|
|
|
- if (disableVideo() || questionDialogVisible.value) {
|
|
|
|
|
- if (videoRef.value) {
|
|
|
|
|
- videoRef.value.pause()
|
|
|
|
|
|
|
+ player = videojs(videoPlayer.value, {
|
|
|
|
|
+ controls: true,
|
|
|
|
|
+ sources: [
|
|
|
|
|
+ {
|
|
|
|
|
+ src: course.value.courseVideoPath,
|
|
|
|
|
+ type: isM3u8 ? 'application/x-mpegURL' : 'video/mp4'
|
|
|
|
|
+ }
|
|
|
|
|
+ ],
|
|
|
|
|
+ preload: 'metadata' // 仅加载元数据,避免预加载整个文件
|
|
|
|
|
+ })
|
|
|
|
|
+
|
|
|
|
|
+ // 如果是m3u8格式,启用HLS支持
|
|
|
|
|
+ if (isM3u8 && !hlsRef.value) {
|
|
|
|
|
+ // 检查是否已加载hls.js插件
|
|
|
|
|
+ if (videojs.getPlugin('hls')) {
|
|
|
|
|
+ hlsRef.value = player.hls()
|
|
|
|
|
+ } else {
|
|
|
|
|
+ console.warn('video.js HLS插件未加载,可能无法正常播放m3u8格式视频')
|
|
|
|
|
+ // 尝试使用hls.js直接播放
|
|
|
|
|
+ if (Hls.isSupported()) {
|
|
|
|
|
+ hlsRef.value = new Hls()
|
|
|
|
|
+ hlsRef.value.loadSource(course.value.courseVideoPath)
|
|
|
|
|
+ hlsRef.value.attachMedia(videoRef.value)
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|