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>
 |