vue2视频video循环渲染卡顿+大视频分段上传

在这里插入图片描述

视频多个一起播放卡顿,所以播放一个其他禁止播放
https://www.h5w3.com/145650.html

大视频分段上传

//组件
<!-- 视频分段上传 -->
<script lang="ts" setup>
import { ElMessage } from 'element-plus'
import SparkMD5 from 'spark-md5'
import { checkFileMd5, uploadShortVideo, videoUpload } from '@/api/common'
const fileList = ref([])
const loading = ref(false)
const chunkSize = ref(0) //分片大小

const emit = defineEmits(['getUrl'])

const uploadFile = async (File) => {
  const file = File.target.files[0] // 文件
  const fileSize = File.target.files[0].size // 文件大小
  const fileName = File.target.files[0].name //文件名称

  let duration: number = 0
  const url = URL.createObjectURL(file)
  const filelement = new Audio(url)
  filelement.addEventListener('loadedmetadata', function (_event) {
    file.duration = filelement.duration
    duration = filelement.duration // 得到视频或音频的时长,单位秒
  })
  console.log('视频或音频的时长,单位秒', file)

  // 文件小于50MB短视频上传
  if (fileSize < 50 * 1024 * 1024) {
    const formData = new FormData()
    formData.append('file', file)
    shortUpload(formData, file)
    return
  }
  loading.value = true
  let chunkSize = 3 * 1024 * 1024 // 分片大小
  let chunkCount = Math.ceil(fileSize / chunkSize) // 分片数量
  let fileMd5 = await getFileMd5(file, chunkCount, chunkSize)

  if (chunkSize > fileSize) {
    // 文件过小就一片
    chunkCount = 1
  }
  const checkForm = new FormData()
  checkForm.append('fileName', File.target.files[0].name)
  checkForm.append('md5', fileMd5.toString())
  //通过秒传接口获取每片大小
  checkUpload(checkForm).then(async (res: any) => {
    if (res.chunkSize) {
      const num = res.chunkSize / 1024 / 1024
      chunkSize = num * 1024 * 1024
      chunkCount = Math.ceil(fileSize / chunkSize) // 分片数量
      fileMd5 = await getFileMd5(file, chunkCount, chunkSize)
      shardingUpload(chunkCount, chunkSize, file, fileMd5, res.missChunkList)
      loading.value = false
    } else {
      ElMessage.error('请重新上传')
      loading.value = false
    }
  })
}

// 获取Md5
const getFileMd5 = (file: File, chunkCount: number, chunkSize: number) => {
  return new Promise((resolve, reject) => {
    const blobSlice = File.prototype.slice
    const chunks = chunkCount
    let currentChunk = 0
    const spark = new SparkMD5.ArrayBuffer()
    const fileReader = new FileReader()
    fileReader.onload = (e) => {
      spark.append(e.target?.result)
      currentChunk++
      if (currentChunk < chunks) {
        loadNext()
      } else {
        const md5 = spark.end()
        resolve(md5)
      }
    }
    fileReader.onerror = (e) => {
      reject(e)
    }
    function loadNext() {
      const start = currentChunk * chunkSize
      let end = start + chunkSize
      if (end > file.size) {
        end = file.size
      }
      fileReader.readAsArrayBuffer(blobSlice.call(file, start, end))
    }
    loadNext()
  })
}

// 短视频上传
const shortUpload = (formData, file) => {
  uploadShortVideo(formData).then((res) => {
    const url = res.data.urlPrefix + '/' + res.data.urlPath
    ElMessage.success('上传成功')
    emit('getUrl', { url: url, file: file })
  })
}

// 校验视频格式,是否上传
const checkUpload = (formatData) => {
  return new Promise((resolve, reject) => {
    checkFileMd5(formatData).then((res) => {
      if (!res.data.formatVerification) {
        ElMessage.error('视频格式不符')
        reject('视频格式不符')
        return
      }
      if (res.data.statusValue === 100) {
        ElMessage.error('视频已存在')
        reject('视频已存在')
        return
      }
      if (res.data.statusValue === 101 || res.data.statusValue === 102) {
        resolve({
          chunkSize: res.data.chunkSize,
          missChunkList: res.data.missChunkList,
        })
      }
    })
  })
}

//上传分片
const shardingUpload = (
  chunkCount,
  chunkSize,
  file,
  fileMd5,
  missChunkList,
) => {
  const arr = []
  loading.value = true
  for (let i = 0; i < chunkCount; i++) {
    const start = i * chunkSize //分片开始
    const end = Math.min(file.size, start + chunkSize) // 分片结束
    const _chunkFile = file.slice(start, end) // 分片文件
    file.filename = file.name

    const formdata = new FormData()
    formdata.append('chunks', chunkCount.toString())
    formdata.append('file', _chunkFile, file.name)
    formdata.append('fileName', file.name)
    formdata.append('md5', fileMd5.toString())

    // 如果部分上传判断哪些片段未上传
    if (missChunkList) {
      missChunkList.includes(String(i)) &&
        formdata.append('chunk', i.toString())
      // missChunkList.includes(String(i)) && arr.push(i)
    } else {
      formdata.append('chunk', i.toString())
    }
    videoUpload(formdata)
      .then((res) => {
        if (res.data.flagLast) {
          ElMessage.success('上传成功')
        }
        loading.value = false
      })
      .catch(() => {
        loading.value = false
      })
  }
}
</script>
<template>
  <div>
    <div v-loading="loading" class="upload-btn">
      <label
        :for="'uploadInput'"
        class="el-button file-btn el-button--primary el-button--medium"
        style="display: flex; align-items: center"
        >{{ '上传视频' }}</label
      >
      <input
        id="uploadInput"
        ref="uploadInput"
        accept="video/*"
        type="file"
        class="el-upload__input"
        @change="uploadFile"
      />
    </div>
  </div>
</template>

//使用
<VideoUploadSection @getUrl="getUrl" />
// 获取视频的地址
  const getUrl = (data) => {
    const obj = {
      videoName: viAddState.form.videoName,
      originalName: data.file.name,
      videoUrl: data.url,
      videoDuration: data.file.duration
    }
    viAddState.fileInfo = obj
    console.log(obj)
  }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值