美文网首页重修前端
js实现截取视频封面功能

js实现截取视频封面功能

作者: 五更月下琉璃 | 来源:发表于2020-06-19 18:01 被阅读0次

    最近被告知要做一个给视频指定时间段截图的功能,不多BB上代码,使用了ivewUI。
    效果图:


    tim_01.png
    <template>
      <div class="home-page">
        <div class="upload">
          <Upload
            multiple
            type="drag"
            style="width:200px"
            :before-upload="UploadVideo"
            action=""
          >
            <div style="padding: 20px 0">
              <Icon type="ios-cloud-upload" size="52" style="color: #24345f"></Icon>
              <p>点击或拖拽上传</p>
            </div>
          </Upload>
        </div>
        <div class="myCover">
          <div class="pic" v-for="(item, index) in showCoverArr" :key="index">
            <img :src="item" />
          </div>
        </div>
      </div>
    </template>
    

    方法

    import utilsTool from "@/lib/utils/index"; //已经封装好,直接调用
    
      data() {
        return {
          videoInfo: {
            url: "",
            play: false,
          },
          cutTime: ['3', '20', '66'], //截图时间点,建议采用%,通过%乘视频时长获取截屏时间
          showCoverArr: [],
        };
      },
    
        UploadVideo(file) {
          this.showCoverArr = [];
          console.log(file);
          if (!/^video\/mp4$/.test(file.type)) {
            this.$Message.warning("视频格式不正确,只支持“.mp4”");
            return false;
          }
          if (file.size / 1024 / 1024 > 100) {
            this.$Message.warning("视频大小不能超过100M");
            return false;
          }
          let url = URL.createObjectURL(file);
          this.videoInfo.src = url;
          console.log(url);
          this.cutVideoCover(url, 0);
        },
        // 视频封面截图(传入截屏时间点)
        cutVideoCover(url, index) {
          utilsTool.GetVideoCover({
            url: url,
            time: this.cutTime[index],
            success: (res) => {
              this.showCoverArr.push(res.base64); //给展示列表传入截图的URL
              console.log(
                "第",index+1,"张",
                "总",this.cutTime.length,"张"
              );
              if(parseInt(this.showCoverArr.length)<parseInt(this.cutTime.length)){
                this.cutVideoCover(url, index+=1);
              }else {
                console.log(this.showCoverArr)
              }
            },
          });
        },
    

    封装的绘制部分

    //压缩图片
    function clipAndCompressCover({ media, currentWidth, currentHeight, success }) {
        // eslint-disable-next-line no-unused-vars
        const that = this;
        const canvas = document.createElement("canvas");
        const area = canvas.getContext("2d");
        const currentScale = currentWidth / currentHeight;
        const targetScale = 750 / 420;
        let targetWidth = 0;
        let targetHeight = 0;
        let clipWidth = 0;
        let clipHeight = 0;
        let quality = 0.95; // 不要用1,会额外增大base64大小。
      
        // 根据视频宽高,决定截图大小
        if (currentScale >= targetScale) {
          targetHeight = currentHeight > 420 ? 420 : currentHeight;
          targetWidth = targetHeight * currentScale;
        } else {
          targetWidth = currentWidth > 750 ? 750 : currentWidth;
          targetHeight = targetWidth / currentScale;
        }
        clipWidth = targetWidth > 750 ? 750 : targetWidth;
        clipHeight = targetHeight > 420 ? 420 : currentHeight;
        canvas.width = clipWidth;
        canvas.height = clipHeight;
      
        area.drawImage(
          media,
          (clipWidth - targetWidth) / 2,
          (clipHeight - targetHeight) / 2,
          targetWidth,
          targetHeight
        );
        var handler = function() {
          const base64 = canvas.toDataURL("image/jpeg", quality);
          getMediaSize({ src: base64 }).then(response => {
            if (response.size / 1024 > 100) {
              quality -= 0.1;
      
              if (quality > 0.2) {
                handler();
              }
            } else {
              success && success(base64);
            }
          });
        };
        handler();
      }
      
      //绘制视频封面图片
      const GetVideoCover = ({ url, time, success }) => {
        const video1 = document.createElement("video");
        video1.src = url;
        video1.style.cssText = "position:fixed; top:0; left:-100%; visibility:hidden";
        video1.onloadeddata = function() {
          let currentTime = time; //截图时间点
          video1.addEventListener("timeupdate", function() {
            clipAndCompressCover({
              media: video1,
              currentWidth: video1.videoWidth,
              currentHeight: video1.videoHeight,
              success: function(base64) {
                video1.remove(video1);
                success({
                  base64: base64
                })
              }
            });
          });
          video1.currentTime = currentTime < 0 ? 1 : currentTime;
        };
        // edge浏览器必须要追加到dom中,才能顺利执行相关事件。
        document.body.appendChild(video1);
      };
    // 获取媒体资源的大小,返回一个Promise对象。用于解决无法直接获取视频或图片的文件大小。
    function getMediaSize({
        src
    }) {
        return new Promise((resolve, reject) => {
            const xhr = new XMLHttpRequest();
    
            // eslint-disable-next-line no-unused-vars
            xhr.onreadystatechange = _ => {
                if (xhr.readyState === 4) {
                    if (xhr.status >= 200 && xhr.status < 300 || xhr.status === 304) {
                        resolve({
                            size: xhr.response.size
                        });
                    } else {
                        reject();
                    }
                }
            };
    
            xhr.open('get', URL.createObjectURL(transformBase64ToBlob(src)));
            xhr.responseType = 'blob';
            xhr.send();
        });
    }
    
    function transformBase64ToBlob(base64) {
        let byteString;
    
        if (base64.split(',')[0].indexOf('base64') >= 0) {
            byteString = atob(base64.split(',')[1]);
        } else {
            byteString = unescape(base64.split(',')[1]);
        }
    
        const mimeString = base64.split(',')[0].split(':')[1].split(';')[0];
        const ia = new Uint8Array(byteString.length);
    
        for (let i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
    
        const blob = new Blob([ia], {
            type: mimeString
        });
    
        return blob;
    }
    export default {
        GetVideoCover,
    };
    

    至此,截图生成的base64编码都有了,只需要放到页面展示即可

    相关文章

      网友评论

        本文标题:js实现截取视频封面功能

        本文链接:https://www.haomeiwen.com/subject/bgbsxktx.html