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 4 import cloneDeep from 'lodash/cloneDeep'
5 5
6 6 export const option = {
7   - dataset: [
8   - {
9   - url: ''
10   - }
11   - ] as any,
  7 + dataset: '',
12 8 autoplay: false,
13 9 }
14 10
... ...
1 1 <template>
2 2 <CollapseItem name="播放器配置" :expanded="true">
3 3 <setting-item-box name="源地址" :alone="true">
4   - <setting-item v-for="(item, index) in optionData.dataset" :key="index">
  4 + <setting-item>
5 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 7 </n-input-group>
8 8 </setting-item>
9 9 </setting-item-box>
... ...
1 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 4 </div>
19 5 </template>
20 6 <script setup lang="ts">
21   -import { PropType, toRefs, watch, shallowReactive, ref, computed } from 'vue'
  7 +import { PropType, toRefs, shallowReactive, watch } from 'vue'
22 8 import { CreateComponentType } from '@/packages/index.d'
23   -import 'video.js/dist/video-js.min.css'
24 9 import { option as configOption } from './config'
25   -import { CameraItem } from './components'
  10 +import { VideoPlay } from './components'
26 11
27 12 const props = defineProps({
28 13 chartConfig: {
... ... @@ -33,54 +18,21 @@ const props = defineProps({
33 18
34 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 23 const option = shallowReactive({
41 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 27 watch(
60   - () => props.chartConfig.option.dataset,
61   - newData => {
  28 + () => dataset?.value,
  29 + (newData: string) => {
62 30 option.dataset = newData
63   - responsive(h.value)
64 31 },
65 32 {
66 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 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>
... ...