视频多个一起播放卡顿,所以播放一个其他禁止播放
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)
}