今天我们写一个视频上传,并截取视频的第一帧作为首图的功能。
我们采用vue的框架,element的el-upload组件库作为基础
先把html写出来
<el-upload accept="video/mp4" :limit="1" ref="videoUpload" :class="{imgUpload: videoWriteFileList.length > 0 }"
action="https://jsonplaceholder.typicode.com/posts/"
list-type="picture-card" :on-exceed="exceedLimit" :data="uploadData" :on-progress="videoprogress"
:before-upload="videobeforeUpload" :file-list="videoFileList"
:on-success="videoSuccess" :on-error="handleError"
:on-preview="videohandlePictureCardPreview"
:on-remove="videohandleRemove">
<i class="el-icon-plus"></i>
</el-upload>
<el-dialog :visible.sync="videodialogVisible" :append-to-body="true">
<video id="upvideo" width="100%" autoplay height="500" :src="dialogImageUrl" alt="" controls></video>
</el-dialog>
tips:复制记得替换action。action为后台上传地址
相关主要实现方法
// 视频上传成功之后调用的方法
videoSuccess(res,file,fileList){
this.findvideocover(file.url,file);
},
//截取视频第一帧作为播放前默认图片
findvideocover(url,file) {
// const video = document.getElementById("myvideo"); // 获取视频对象
const video = document.createElement("video") // 也可以自己创建video
video.src=url // url地址 url跟 视频流是一样的
// var canvas = document.getElementById('mycanvas') // 获取 canvas 对象
var canvas = document.createElement('canvas') // 获取 canvas 对象
const ctx = canvas.getContext('2d'); // 绘制2d
video.crossOrigin = 'anonymous' // 解决跨域问题,也就是提示污染资源无法转换视频
video.currentTime = 1 // 第一帧
video.oncanplay = () => {
console.log(video.clientWidth, video.clientHeight);
canvas.width = video.clientWidth ? video.clientWidth : 320; // 获取视频宽度
canvas.height = video.clientHeight ? video.clientHeight : 320; //获取视频高度
// 利用canvas对象方法绘图
ctx.drawImage(video, 0, 0, canvas.width,canvas.height)
// 转换成base64形式
this.videoFirstimgsrc = canvas.toDataURL ("image/png"); // 截取后的视频封面
file.url = this.videoFirstimgsrc;
// base64转成bolb文件
const fileBolb = this.base64toFile(this.videoFirstimgsrc, this.getFileName(file))
// 把首图上传生成云上地址
this.getFirstPngUrl(fileBolb);
video.remove();
canvas.remove();
}
},
base64toFile (baseUrl, filename = 'file') {
let arr = baseUrl.split(',');
let type = arr[0].match(/:(.*?);/)[1]; // 解锁图片类型
let bytes = atob(arr[1]); // 解码base64
let n = bytes.length
let bufferArray = new Uint8Array(n);
while (n--) {
bufferArray[n] = bytes.charCodeAt(n);
}
return new File([bufferArray ],filename,{ type });
},
getFirstPngUrl(file){
const fd = new FormData();
fd.append('file',file);
fd.append('sid',this.uploadData.sid);
// this.$post为我自己封装的axios的post方法。可直接用axios的post方法
this.$post('http://www.baidu.com', fd, { headers: {'Content-Type': 'multipart/form-data', },}).then(res=>{
this.videoFirstimgsrc = res.url;
this.videoWriteFileList[0].url = res.url;
})
},
getFileName(file){
const type = file.raw.type.split("/")[1];
let name = '';
if(type){
name = file.raw.name.substring(0, file.raw.name.indexOf(`.${type}`));
}
return `${name}.png`;
},