el-upload 上传视频时,动态截取视频第一帧画面作为封面展示

        最近项目有上传视频的需求,但 Element 的 el-upload上传视频后,回显异常,不会显示视频内容(如下图)

el-upload 上传视频时,动态截取视频第一帧画面作为封面展示_第1张图片

        通过在网上查找截取视频第一帧的方法,自己稍加修改,得以正常显示封面,如下图:

el-upload 上传视频时,动态截取视频第一帧画面作为封面展示_第2张图片

        本方法采用前端动态获取第一帧画面,后端不保存当前视频第一帧信息。这样做,好处是:修改及删除视频时,不用做额外的关联封面处理,减少交互以及省去服务器保存封面资源,不好的地方就是:如果视频过大,获取第一帧封面的时间会比较长,本人亲测,40几M的视频,差不多2-3秒左右加载封面出来,但针对此问题,可以先默认加载系统预设默认封面,待视频处理完后,再加载第一帧画面。

1. JS 中获取视频第一帧方法

        /**
         * 获取视频第一帧作为回显封面
         * @param file 至少应包含url信息,即 {url: ""}
         */
        getVideoCover(file) {
            let _self = this;
            _self.$set(file, 'videoUrl', _self.$utils.deepClone(file.url)); //备份视频源路径,用于后续预览展示
            
            const video = document.createElement("video") // 也可以自己创建video
            video.src = file.url // url地址 url跟 视频流是一样的
            file.url = videoDefCover;   //设置默认封面,videoDefCover 为预制的默认封面,不需要可去除或替换成自己的
            let 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形式
                let _videoFirstimgsrc = canvas.toDataURL ("image/png"); // 截取后的视频封面
                _self.$set(file, 'url', _videoFirstimgsrc);   //重置文件的url为当前截取的封面,用于 el-upload展示
                video.remove();
                canvas.remove();
            }
        },

2. el-upload 设置

2.1 上传成功后回显调用

        handleUploadSuccess(response, file, fileList) {     //为 el-upload on-success 方法实现
            let _self = this;
            _self.fileList = fileList;
            if (response.code != 0) {
                _self.$message({
                    message: '附件上传失败',
                    type: 'error'
                })
                _self.fileList.splice(_self.fileList.indexOf(file, 1))
            } else {
                let _fileName = file.name;
                if (_self.$utils.getFileIsVideo(_fileName)) {   //getFileIsVideo 为我本地自定义判断是否是视频方法,可自己修改
                    //视频附件,获取第一帧画面作为 封面展示
                    _self.getVideoCover(file);
                }
            }
        },

2.2 页面编辑、数据回显

        /**
         * 查看详情时附件回显
         **/
        setFileList(_fileList) {
            let _self = this;
            if (_self.$utils.isNotEmpty(_fileList)) {
                for (let obj of _fileList) {
                    //视频附件,获取第一帧画面作为 封面展示
                    let _fileName = obj.name;
                    if (_self.$utils.getFileIsVideo(_fileName)) {   //getFileIsVideo为我自定义的判断是否是视频的方法,可以自己修改
                        //视频附件,获取第一帧画面作为 封面展示
                        _self.getVideoCover(obj);
                    }
                }
            }
            _self.fileList = _fileList;     //fileList 为 Element file-list 参数值
        },

 至此处理完成。

        预览时,在预览弹窗中判断是否是视频,如果是视频的话,直接取文件的 videoUrl 参数值进行加载展示。

你可能感兴趣的:(Vue,elementui,前端,el-upload)