Commit bee124951bb1ea95a0f1db081b9f4a4f5fb7c9c5

Authored by fengwotao
1 parent 0794e0b7

perf(src/packages): 优化单个摄像头

1 -<template>  
2 - <video  
3 - crossOrigin="anonymous"  
4 - :id="`my-player${index}`"  
5 - ref="videoRef"  
6 - class="video-js my-video vjs-theme-city vjs-big-play-centered"  
7 - >  
8 - <source :src="sourceSrc" />  
9 - </video>  
10 -</template>  
11 -<script setup lang="ts">  
12 -import { onMounted, ref, onUnmounted, watch } from 'vue'  
13 -import videojs from 'video.js'  
14 -import type { VideoJsPlayerOptions } from 'video.js'  
15 -import 'video.js/dist/video-js.min.css'  
16 -  
17 -const props = defineProps({  
18 - sourceSrc: {  
19 - type: String  
20 - },  
21 - name: {  
22 - type: String  
23 - },  
24 - avatar: {  
25 - type: String  
26 - },  
27 - index: {  
28 - type: Number  
29 - },  
30 - autoplay: {  
31 - type: Boolean,  
32 - default: false  
33 - }  
34 -})  
35 -  
36 -// video标签  
37 -const videoRef = ref<HTMLElement | null>(null)  
38 -  
39 -// video实例对象  
40 -let videoPlayer: videojs.Player | null = null  
41 -  
42 -//options配置  
43 -const options: VideoJsPlayerOptions = {  
44 - language: 'zh-CN', // 设置语言  
45 - controls: true, // 是否显示控制条  
46 - preload: 'auto', // 预加载  
47 - autoplay: props.autoplay, // 是否自动播放  
48 - fluid: false, // 自适应宽高  
49 - poster: props?.avatar || '',  
50 - src: props?.sourceSrc || '', // 要嵌入的视频源的源 URL  
51 - muted: true,  
52 - userActions: {  
53 - hotkeys: true  
54 - }  
55 -}  
56 -  
57 -// 初始化videojs  
58 -const initVideo = () => {  
59 - if (videoRef.value) {  
60 - // 创建 video 实例  
61 - videoPlayer = videojs(videoRef.value, options)  
62 - }  
63 -}  
64 -  
65 -watch(  
66 - () => props.sourceSrc,  
67 - (newData: any) => {  
68 - // props.sourceSrc = newData  
69 - videoPlayer?.src(newData) as any  
70 - videoPlayer?.play()  
71 - },  
72 - {  
73 - immediate: true  
74 - }  
75 -)  
76 -  
77 -onMounted(() => {  
78 - initVideo()  
79 -})  
80 -  
81 -onUnmounted(() => {  
82 - handleVideoDispose()  
83 -})  
84 -  
85 -//播放  
86 -const handleVideoPlay = () => videoPlayer?.play()  
87 -  
88 -const handleVideoDispose = () => videoPlayer?.dispose() && videoPlayer?.pause()  
89 -//暂停  
90 -defineExpose({  
91 - handleVideoPlay,  
92 - handleVideoDispose  
93 -})  
94 -</script>  
95 -  
96 -<style lang="scss" scoped>  
97 -.my-video {  
98 - width: 100%;  
99 - height: 100%;  
100 -}  
101 -</style>  
  1 +<template>
  2 + <div class="videoPlay">
  3 + <video crossOrigin="anonymous" ref="videoRef" class="video-js vjs-default-skin vjs-big-play-centered" controls>
  4 + <source :src="path" />
  5 + </video>
  6 + </div>
  7 +</template>
  8 +<script lang="ts" setup>
  9 +import { nextTick, onBeforeUnmount, onMounted, ref, watch } from 'vue'
  10 +import videojs, { VideoJsPlayer } from 'video.js'
  11 +import type { VideoJsPlayerOptions } from 'video.js'
  12 +import 'video.js/dist/video-js.css'
  13 +import zh from 'video.js/dist/lang/zh-CN.json'
  14 +
  15 +const props = withDefaults(
  16 + defineProps<{
  17 + path: string
  18 + autoPlay?: boolean
  19 + h?: number
  20 + }>(),
  21 + { autoPlay: false }
  22 +)
  23 +
  24 +const videoRef = ref()
  25 +
  26 +let player: VideoJsPlayer
  27 +
  28 +const initPlay = async () => {
  29 + videojs.addLanguage('zh-CN', zh)
  30 + await nextTick()
  31 + const options: VideoJsPlayerOptions = {
  32 + muted: true,
  33 + controls: true,
  34 + autoplay: props.autoPlay,
  35 + src: props?.path,
  36 + language: 'zh-CN',
  37 + techOrder: ['html5']
  38 + }
  39 + player = videojs(videoRef.value, options, () => {
  40 + videojs.log('播放器已经准备好了!')
  41 + if (props.autoPlay) {
  42 + player.play()
  43 + }
  44 + player.on('ended', () => {
  45 + videojs.log('播放结束了!')
  46 + })
  47 + player.on('error', () => {
  48 + videojs.log('播放器解析出错!')
  49 + })
  50 + })
  51 +}
  52 +
  53 +onMounted(() => {
  54 + initPlay()
  55 +})
  56 +
  57 +//直接改变路径测试
  58 +watch(
  59 + () => props.path,
  60 + () => {
  61 + player?.pause()
  62 + player?.src(props.path)
  63 + player?.load()
  64 + if (props.path) {
  65 + player?.play()
  66 + }
  67 + },
  68 + {
  69 + immediate: true
  70 + }
  71 +)
  72 +
  73 +onBeforeUnmount(() => {
  74 + player?.dispose()
  75 +})
  76 +</script>
  77 +<style lang="scss" scoped>
  78 +.videoPlay {
  79 + flex: 1;
  80 + height: v-bind('`${h}px`');
  81 +
  82 + .video-js {
  83 + height: 100%;
  84 + width: 100%;
  85 + }
  86 +}
  87 +</style>
1 -import CameraItem from './CameraItem.vue' 1 +import VideoPlay from './VideoPlay.vue'
2 2
3 -export { CameraItem } 3 +export { VideoPlay }
@@ -4,11 +4,7 @@ import { SingleCameraConfig } from './index' @@ -4,11 +4,7 @@ import { SingleCameraConfig } from './index'
4 import cloneDeep from 'lodash/cloneDeep' 4 import cloneDeep from 'lodash/cloneDeep'
5 5
6 export const option = { 6 export const option = {
7 - dataset: [  
8 - {  
9 - url: ''  
10 - }  
11 - ] as any, 7 + dataset: '',
12 autoplay: false, 8 autoplay: false,
13 } 9 }
14 10
1 <template> 1 <template>
2 <CollapseItem name="播放器配置" :expanded="true"> 2 <CollapseItem name="播放器配置" :expanded="true">
3 <setting-item-box name="源地址" :alone="true"> 3 <setting-item-box name="源地址" :alone="true">
4 - <setting-item v-for="(item, index) in optionData.dataset" :key="index"> 4 + <setting-item>
5 <n-input-group> 5 <n-input-group>
6 - <n-input v-model:value="item.url" size="small" placeholder="请输入源地址"></n-input> 6 + <n-input v-model:value="optionData.dataset" size="small" placeholder="请输入源地址"></n-input>
7 </n-input-group> 7 </n-input-group>
8 </setting-item> 8 </setting-item>
9 </setting-item-box> 9 </setting-item-box>
1 <template> 1 <template>
2 - <div class="banner-box" ref="root">  
3 - <n-grid x-gap="12" :y-gap="12" :cols="computedCols">  
4 - <n-gi v-for="(item, index) in option.dataset" :key="index + item">  
5 - <div class="camera-container">  
6 - <CameraItem  
7 - ref="cameraRef"  
8 - :name="item.name"  
9 - :avatar="item.avatar"  
10 - :key="item + index"  
11 - :sourceSrc="item.url"  
12 - :index="index"  
13 - :autoplay="autoplay"  
14 - />  
15 - </div>  
16 - </n-gi>  
17 - </n-grid> 2 + <div>
  3 + <VideoPlay :h="h" :path="option.dataset" :autoPlay="autoplay" />
18 </div> 4 </div>
19 </template> 5 </template>
20 <script setup lang="ts"> 6 <script setup lang="ts">
21 -import { PropType, toRefs, watch, shallowReactive, ref, computed } from 'vue' 7 +import { PropType, toRefs, shallowReactive, watch } from 'vue'
22 import { CreateComponentType } from '@/packages/index.d' 8 import { CreateComponentType } from '@/packages/index.d'
23 -import 'video.js/dist/video-js.min.css'  
24 import { option as configOption } from './config' 9 import { option as configOption } from './config'
25 -import { CameraItem } from './components' 10 +import { VideoPlay } from './components'
26 11
27 const props = defineProps({ 12 const props = defineProps({
28 chartConfig: { 13 chartConfig: {
@@ -33,54 +18,21 @@ const props = defineProps({ @@ -33,54 +18,21 @@ const props = defineProps({
33 18
34 const { h } = toRefs(props.chartConfig.attr) 19 const { h } = toRefs(props.chartConfig.attr)
35 20
36 -const { autoplay } = toRefs(props.chartConfig.option)  
37 -  
38 -const responsiveComputeValue = ref(0) 21 +const { autoplay, dataset } = toRefs(props.chartConfig.option)
39 22
40 const option = shallowReactive({ 23 const option = shallowReactive({
41 dataset: configOption.dataset 24 dataset: configOption.dataset
42 }) 25 })
43 26
44 -const computedCols = computed(() => {  
45 - if (option.dataset.length <= 1) return 1  
46 - if (option.dataset.length <= 4) return 2  
47 - return 3  
48 -})  
49 -  
50 -const cameraRef = ref<InstanceType<typeof CameraItem>>()  
51 -  
52 -const responsive = (value: number) => {  
53 - responsiveComputeValue.value = value  
54 - if (option.dataset.length <= 2) responsiveComputeValue.value = value  
55 - if (option.dataset.length > 2 && option.dataset.length <= 4) responsiveComputeValue.value = value / 2.03  
56 - if (option.dataset.length > 4 && option.dataset.length <= 9) responsiveComputeValue.value = value / 3.1  
57 -}  
58 -  
59 watch( 27 watch(
60 - () => props.chartConfig.option.dataset,  
61 - newData => { 28 + () => dataset?.value,
  29 + (newData: string) => {
62 option.dataset = newData 30 option.dataset = newData
63 - responsive(h.value)  
64 }, 31 },
65 { 32 {
66 immediate: true, 33 immediate: true,
67 - deep: true  
68 - }  
69 -)  
70 -  
71 -watch(  
72 - () => h.value,  
73 - newData => responsive(newData),  
74 - {  
75 - immediate: true  
76 } 34 }
77 ) 35 )
78 </script> 36 </script>
79 37
80 -<style lang="scss" scoped>  
81 -.banner-box {  
82 - .camera-container {  
83 - height: v-bind('`${responsiveComputeValue}px`');  
84 - }  
85 -}  
86 -</style> 38 +<style lang="scss" scoped></style>