index.vue 4.71 KB
<script setup lang="ts">
import { Spin } from 'ant-design-vue'
import { computed, nextTick, onMounted, onUnmounted, ref, toRaw, unref } from 'vue'
import 'video.js/dist/video-js.css'

import type { VideoJsPlayerOptions } from 'video.js'
import { BasicVideoPlay } from './component/index.ts'
import { VideoPlayerType, getVideoTypeByUrl, isRtspProtocol, useFingerprint } from './component/config'

import { getJwtToken, getShareJwtToken } from '@/utils/auth'
import { isLightboxMode, isShareMode } from '@/utils/env'
import type { CreateComponentType } from '@/core/Library/types'
import { closeFlvPlay, getFlvPlayUrl, getStreamingPlayUrl, getVideoControlStart } from '@/api/video'
import { useContentDataStore } from '@/store/modules/contentData'
import { VideoAccessModeEnum } from '@/enums/videoEnum'

const props = defineProps<{
  config: CreateComponentType

}>()

// 获取节点数据
const contentDataStore = useContentDataStore()
const { getResult } = useFingerprint()
const loading = ref(false)

const getOptions = computed<VideoJsPlayerOptions>(() => {
  const { config } = props || {}
  const { cellBounds } = config || {}
  const { height, width } = cellBounds as any
  return { height, width }
})

// 存储视频数据
const videoConfig = computed(() => {
  return contentDataStore?.contentData.filter((item) => {
    return props.config.cellInfo?.id === item.id
  })
})

// const loading = ref<boolean>(false)
const exampleVideoPlay = 'https://interactive-examples.mdn.mozilla.net/media/cc0-videos/flower.webm'

const basicVideoPlayEl = ref<Nullable<InstanceType<typeof BasicVideoPlay>>>(null)
const withToken = ref(false)
const playSource = ref<Record<'src' | 'type', string>>(
  {} as unknown as Record<'src' | 'type', string>,
)

// 数据绑定获取的url
const handleGetVideoPlay = async () => {
  try {
    loading.value = true
    const { dataSourceJson } = unref(videoConfig)[0] || {}
    const { videoOption } = dataSourceJson || {}
    const { id, accessMode, videoUrl, deviceId, channelId } = videoOption || {}
    let type = getVideoTypeByUrl(videoUrl!)
    let playUrl = videoUrl
    // 判断是否是流媒体播放
    if (accessMode === VideoAccessModeEnum.Streaming && id) {
      const { data: { url } = { url: '' } } = await getStreamingPlayUrl(id!)
      playUrl = url
      playUrl && (type = getVideoTypeByUrl(playUrl!))
    }
    else if (accessMode === VideoAccessModeEnum.GBT28181 && deviceId && channelId) {
      const {
        data: { flv },
      } = await getVideoControlStart({ channelId, deviceId })

      playUrl = flv
      type = VideoPlayerType.flv
    }

    // 判断是否是rtsp播放
    if (isRtspProtocol(videoUrl!)) {
      const result = await getResult()
      const { visitorId } = result
      playUrl = getFlvPlayUrl(playUrl!, visitorId)
      withToken.value = true
    }

    playSource.value = {
      src: playUrl!,
      type,
    }

    const instance = unref(basicVideoPlayEl)?.customInit((options) => {
      if (unref(withToken)) {
        (options as any).flvjs.config.headers = {
          'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}`,
        }
      }
      return {
        ...options,
        sources: [toRaw(unref(playSource))],
      } as VideoJsPlayerOptions
    })

    instance?.play()
  }
  finally {
    loading.value = false
  }
}

// 默认播放
const handleSelectPreview = () => {
  // loading.value = false
  const instance = unref(basicVideoPlayEl)?.customInit((options) => {
    withToken.value = true
    if (unref(withToken)) {
      (options as any).flvjs.config.headers = {
        'X-Authorization': `Bearer ${isShareMode() ? getShareJwtToken() : getJwtToken()}`,
      }
    }
    return {
      ...options,
      sources: [{ type: getVideoTypeByUrl(exampleVideoPlay), src: exampleVideoPlay }],
    } as VideoJsPlayerOptions
  })

  instance?.play()
}

onMounted(async () => {
  await nextTick()
  isLightboxMode() || isShareMode()
    ? handleGetVideoPlay()
    : handleSelectPreview()
})

onUnmounted(async () => {
  const { visitorId } = await getResult()
  const { dataSourceJson } = unref(videoConfig)[0] || {}
  const { videoOption } = dataSourceJson || {}
  const { videoUrl } = videoOption || {}
  isRtspProtocol(videoUrl!) && closeFlvPlay(videoUrl!, visitorId)
  await nextTick()
  unref(basicVideoPlayEl)?.getInstance()?.dispose()
})
</script>

<template>
  <div class="w-full h-full flex justify-center items-center">
    <Spin :spinning="loading">
      <BasicVideoPlay
        ref="basicVideoPlayEl" :options="getOptions" :with-token="withToken"
        :immediate-init-on-mounted="false"
      />
    </Spin>
  </div>
</template>

<style lang="less" scoped>
.video-spin {
  @apply w-full h-full;

  :deep(.ant-spin-container) {
    @apply w-full h-full;
  }
}
</style>