1
|
1
|
<template>
|
2
|
2
|
<div class="go-content-box" :style="{ width: w + 'px', height: h + 'px' }">
|
3
|
|
- <video
|
4
|
|
- crossOrigin="anonymous"
|
5
|
|
- :id="`my-player${index}`" ref="videoRef" class="video-js my-video vjs-theme-city vjs-big-play-centered">
|
6
|
|
- <source :src="sourceSrc" />
|
|
3
|
+ <video crossOrigin="anonymous" :id="`my-player${index}`" ref="videoRef"
|
|
4
|
+ class="video-js my-video vjs-theme-city vjs-big-play-centered">
|
7
|
5
|
</video>
|
8
|
6
|
</div>
|
9
|
7
|
</template>
|
10
|
8
|
<script setup lang="ts">
|
11
|
9
|
import { onMounted, ref, onUnmounted, watch } from 'vue'
|
12
|
10
|
import videojs from 'video.js'
|
|
11
|
+import 'videojs-flvjs-es6'
|
13
|
12
|
import type { VideoJsPlayerOptions } from 'video.js'
|
14
|
13
|
import 'video.js/dist/video-js.min.css'
|
15
|
14
|
|
...
|
...
|
@@ -36,6 +35,37 @@ const props = defineProps({ |
36
|
35
|
}
|
37
|
36
|
})
|
38
|
37
|
|
|
38
|
+enum VideoPlayerType {
|
|
39
|
+ m3u8 = 'application/x-mpegURL',
|
|
40
|
+ mp4 = 'video/mp4',
|
|
41
|
+ webm = 'video/webm',
|
|
42
|
+ flv = 'video/x-flv',
|
|
43
|
+}
|
|
44
|
+
|
|
45
|
+const isRtspProtocol = (url: string) => {
|
|
46
|
+ const reg = /^rtsp:\/\//g;
|
|
47
|
+ return reg.test(url);
|
|
48
|
+};
|
|
49
|
+
|
|
50
|
+const getVideoTypeByUrl = (url = '') => {
|
|
51
|
+
|
|
52
|
+ try {
|
|
53
|
+ const { protocol, pathname } = new URL(url)
|
|
54
|
+
|
|
55
|
+ if (isRtspProtocol(protocol)) return VideoPlayerType.flv
|
|
56
|
+
|
|
57
|
+ const reg = /[^.]\w*$/
|
|
58
|
+ const mathValue = pathname.match(reg) || []
|
|
59
|
+ const ext = mathValue[0] as keyof typeof VideoPlayerType || 'webm'
|
|
60
|
+ const type = VideoPlayerType[ext]
|
|
61
|
+ return type ? type : VideoPlayerType.webm
|
|
62
|
+ } catch (error) {
|
|
63
|
+ console.error(error)
|
|
64
|
+ return VideoPlayerType.webm
|
|
65
|
+ }
|
|
66
|
+};
|
|
67
|
+
|
|
68
|
+
|
39
|
69
|
// video标签
|
40
|
70
|
const videoRef = ref<HTMLElement | null>(null)
|
41
|
71
|
|
...
|
...
|
@@ -43,33 +73,56 @@ const videoRef = ref<HTMLElement | null>(null) |
43
|
73
|
let videoPlayer: videojs.Player | null = null
|
44
|
74
|
|
45
|
75
|
//options配置
|
46
|
|
-const options: VideoJsPlayerOptions = {
|
|
76
|
+const options: VideoJsPlayerOptions & Recordable = {
|
47
|
77
|
language: 'zh-CN', // 设置语言
|
48
|
78
|
controls: true, // 是否显示控制条
|
49
|
79
|
preload: 'auto', // 预加载
|
50
|
80
|
autoplay: true, // 是否自动播放
|
51
|
81
|
fluid: false, // 自适应宽高
|
52
|
82
|
poster: props?.avatar || '',
|
53
|
|
- src: props?.sourceSrc || '', // 要嵌入的视频源的源 URL
|
|
83
|
+ // src: getSource() || '', // 要嵌入的视频源的源 URL
|
|
84
|
+ sources: [],
|
54
|
85
|
muted: true,
|
55
|
86
|
userActions: {
|
56
|
87
|
hotkeys: true
|
57
|
|
- }
|
|
88
|
+ },
|
|
89
|
+ techOrder: ['html5', 'flvjs'],
|
|
90
|
+ flvjs: {
|
|
91
|
+ mediaDataSource: {
|
|
92
|
+ isLive: true,
|
|
93
|
+ cors: true,
|
|
94
|
+ withCredentials: false,
|
|
95
|
+ }
|
|
96
|
+ },
|
|
97
|
+}
|
|
98
|
+
|
|
99
|
+
|
|
100
|
+async function getSource() {
|
|
101
|
+ return [
|
|
102
|
+ {
|
|
103
|
+ type: getVideoTypeByUrl(props.sourceSrc),
|
|
104
|
+ src: props.sourceSrc || ''
|
|
105
|
+ }
|
|
106
|
+ ]
|
58
|
107
|
}
|
59
|
108
|
|
60
|
109
|
// 初始化videojs
|
61
|
|
-const initVideo = () => {
|
|
110
|
+const initVideo = async () => {
|
62
|
111
|
if (videoRef.value) {
|
63
|
|
- // 创建 video 实例
|
64
|
|
- videoPlayer = videojs(videoRef.value, options)
|
|
112
|
+ // 创建 video 实例
|
|
113
|
+ options.sources = await getSource()
|
|
114
|
+ if (options.sources && options.sources.length) {
|
|
115
|
+ videoPlayer = videojs(videoRef.value, options)
|
|
116
|
+ }
|
65
|
117
|
}
|
66
|
118
|
}
|
67
|
119
|
|
68
|
120
|
watch(
|
69
|
121
|
() => props.sourceSrc,
|
70
|
|
- (newData: any) => {
|
|
122
|
+ async (newData: any) => {
|
|
123
|
+ const result = await getSource()
|
71
|
124
|
// props.sourceSrc = newData
|
72
|
|
- videoPlayer?.src(newData) as any
|
|
125
|
+ videoPlayer?.src(result) as any
|
73
|
126
|
videoPlayer?.play()
|
74
|
127
|
},
|
75
|
128
|
{
|
...
|
...
|
|