181 lines
5.8 KiB
Plaintext
181 lines
5.8 KiB
Plaintext
<template>
|
|
<div style="text-align: center">
|
|
<div style="display: flex;justify-content: center">
|
|
<video v-if="videoSrc" id="video" controls crossorigin="anonymous" width="400" height="270"">
|
|
<source :src="videoSrc" type="video/mp4">
|
|
无法播放,请点击转码
|
|
</video>
|
|
<div v-else style="border:2px dashed #999;border-radius: 10px;cursor:pointer;width:400px;height:270px;display: flex;justify-content: center;align-items: center" @click="$refs.fileInput.click()">
|
|
请选择视频文件
|
|
</div>
|
|
</div>
|
|
<input v-show="false" ref="fileInput" type="file" accept="video/*" @change="fileChange">
|
|
<div v-if="isVideoToMp4" style="display: flex;align-items: center;justify-content: right;margin-top: 10px;">
|
|
<div>转码进度: </div>
|
|
<el-progress style="width: 200px" :percentage="percentage" :format="() => {return percentage + '%'}" />
|
|
</div>
|
|
<div style="margin-top: 10px;display: flex;justify-content: right;align-items: center">
|
|
<el-button size="small" type="primary" :disabled="isVideoToMp4 || isDisabled" @click="$refs.fileInput.click()">选择文件</el-button>
|
|
<el-button v-if="isNeedToMp4" size="small" type="primary" :disabled="(videoSrc ? false : true) || isVideoToMp4 || isDisabled" @click="videoToMp4">转码</el-button>
|
|
<el-button size="small" type="primary" :disabled="(videoSrc ? false : true) || isVideoToMp4 || isDisabled" @click="upload">上传</el-button>
|
|
</div>
|
|
</div>
|
|
</template>
|
|
|
|
<script>
|
|
import { createFFmpeg, fetchFile } from '@ffmpeg/ffmpeg'
|
|
const ffmpeg = createFFmpeg({
|
|
log: true,
|
|
corePath: './ffmpeg-core.js'
|
|
})
|
|
|
|
export default {
|
|
props: {
|
|
},
|
|
data() {
|
|
return {
|
|
isDisabled: false,
|
|
imgList: [],
|
|
fileObj: null,
|
|
videoList: [],
|
|
videoSrc: null,
|
|
file: null,
|
|
dataBuffer: null,
|
|
percentage: 0,
|
|
isVideoToMp4: false,
|
|
isNeedToMp4: false
|
|
}
|
|
},
|
|
watch: {
|
|
},
|
|
mounted() {
|
|
},
|
|
methods: {
|
|
async uploadVideo(objectName, file) {
|
|
try {
|
|
this.isDisabled = true
|
|
const result = await this.OSSclient.put(objectName, file)
|
|
this.$emit('uploadOver', true, result, this.file.name)
|
|
} catch (e) {
|
|
console.log(e)
|
|
this.isDisabled = false
|
|
this.$emit('uploadOver', false)
|
|
}
|
|
},
|
|
upload() {
|
|
if (document.querySelector('#video').readyState === 0 && document.querySelector('#video').buffered.length === 0) {
|
|
this.$alert(this.$t('components:uploadvideo:message:xf2'))
|
|
this.isNeedToMp4 = true
|
|
return
|
|
}
|
|
this.uploadVideo(`file/videofile/${this.file.name.split('.')[0]}${new Date().getTime()}.mp4`, this.dataBuffer)
|
|
},
|
|
async videoToMp4() {
|
|
// 页面是否在安全上下文中
|
|
// https 或者 本地开发环境才是安全上下文
|
|
if (!window.isSecureContext) {
|
|
this.$alert(this.$t('components:uploadvideo:message:xf3'))
|
|
return
|
|
}
|
|
// 顶部文档是否开启跨源隔离
|
|
if (!window.crossOriginIsolated) {
|
|
this.$alert(this.$t('components:uploadvideo:message:xf4'))
|
|
return
|
|
}
|
|
this.$message.success(this.$t('components:uploadvideo:message:xf5'))
|
|
if (!ffmpeg.isLoaded()) {
|
|
await ffmpeg.load()
|
|
}
|
|
this.percentage = 0
|
|
this.isVideoToMp4 = true
|
|
ffmpeg.setProgress(({ ratio }) => {
|
|
console.log(ratio)
|
|
if (ratio * 100 < 1) {
|
|
this.percentage = parseInt(0)
|
|
} else {
|
|
this.percentage = parseInt(ratio * 100)
|
|
}
|
|
})
|
|
ffmpeg.FS('writeFile', 'input.mp4', await fetchFile(this.videoSrc))
|
|
await ffmpeg.run('-i', 'input.mp4', 'output.mp4')
|
|
this.videoSrc = null
|
|
const data = ffmpeg.FS('readFile', 'output.mp4')
|
|
this.dataBuffer = new Blob([data.buffer], { type: 'video/mp4' })
|
|
this.$message.success(this.$t('components:uploadvideo:message:xf6'))
|
|
setTimeout(() => {
|
|
this.videoSrc = URL.createObjectURL(this.dataBuffer)
|
|
this.isVideoToMp4 = false
|
|
this.isNeedToMp4 = false
|
|
process.exit(0)
|
|
}, 50)
|
|
},
|
|
fileChange(e) {
|
|
this.videoSrc = null
|
|
const files = e.target.files || e.dataTransfer.files
|
|
this.file = files[0]
|
|
var reader = new FileReader()
|
|
reader.readAsArrayBuffer(this.file)
|
|
reader.onloadend = async(e) => {
|
|
this.dataBuffer = new Blob([e.target.result], { type: 'video/mp4' })
|
|
this.videoSrc = URL.createObjectURL(this.dataBuffer)
|
|
this.$message.success(this.$t('components:uploadvideo:message:xf7'))
|
|
e.target.files = []
|
|
}
|
|
},
|
|
deleteimg(index) {
|
|
this.imgList.splice(index, 1)
|
|
},
|
|
jietu() {
|
|
this.screenShot('video')
|
|
},
|
|
screenShot(id) {
|
|
var player = document.getElementById(id)
|
|
var canvas = document.createElement('canvas')
|
|
var img = document.createElement('img')
|
|
canvas.width = player.videoWidth
|
|
canvas.height = player.videoHeight
|
|
canvas.getContext('2d').drawImage(player, 0, 0, canvas.width, canvas.height)
|
|
var dataURL = canvas.toDataURL('image/png')
|
|
img.src = dataURL
|
|
img.width = player.clientWidth
|
|
img.height = player.clientHeight
|
|
img.style.objectFit = 'contain'
|
|
this.imgList.push(dataURL)
|
|
},
|
|
downFile(data, fileName) {
|
|
var save_link = document.createElementNS(
|
|
'http://www.jumi.com',
|
|
'a'
|
|
)
|
|
save_link.href = data
|
|
save_link.download = fileName
|
|
var event = document.createEvent('MouseEvents')
|
|
event.initMouseEvent(
|
|
'click',
|
|
true,
|
|
false,
|
|
window,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
false,
|
|
false,
|
|
false,
|
|
false,
|
|
0,
|
|
null
|
|
)
|
|
save_link.dispatchEvent(event)
|
|
}
|
|
}
|
|
}
|
|
</script>
|
|
<style lang='scss'>
|
|
#cutImage{
|
|
img{
|
|
}
|
|
}
|
|
</style>
|