• H5纯前端获取视频第一帧、大小、尺寸、类型等


    纯前端获取视频第一帧、大小、尺寸、类型等

    需求背景

    最近有个视频上传的需求,需要对上传上传到OSS的视频做一些限制,并且在上传之前判断,视频的大小、尺寸、比例、时长等等。心里一直想着OSS能直接把视频的相关信息返回;毕竟图片是有很多信息返回的;
    然而经过确认之后,发现屁都没有……
    那就只能自己写了,百度了一下,并没有特别全的方案,那就自己动手写个吧。

    视频加载基本介绍

    在视频/音频(audio/video)加载过程中,事件的触发顺序如下:

    1. onloadstart (浏览器开始寻找指定资源)
    2. ondurationchange (视频/音频 的时长发生变化时触发)
    3. onloadedmetadata (指定视频/音频 的元数据加载后触发)
    4. onloadeddata (当前帧的数据加载完成且还没有足够的数据播放)
    5. onprogress (下载指定的视频/音频 时触发)
    6. oncanplay (用户可以开始播放视频/音频 时触发)
    7. oncanplaythrough (可以正常播放且无需停顿和缓冲时触发)

    写个小代码

    获得时长

    找了一个相对好一点的方案,然后准备改巴改巴……

    html

        <div id="input-upload-file" class="box-shadow">
            <span>upload! (ღ˘⌣˘ღ)</span>
            <input type="file" class="upload" id="fileUp" name="fileUpload">
        </div>
        <pre id="infos"></pre>

    js

        <script>
            var myVideos = [];
    
            window.URL = window.URL || window.webkitURL;
    
            document.getElementById('fileUp').onchange = setFileInfo;
    
            function setFileInfo() {
                var files = this.files;
                myVideos.push(files[0]);
                var video = document.createElement('video');
                video.preload = 'metadata';
    
                video.onloadedmetadata = function() {
                    window.URL.revokeObjectURL(video.src);
                    var duration = video.duration; // 得到时长
                    myVideos[myVideos.length - 1].duration = duration;
                    updateInfos();
                }
                video.src = URL.createObjectURL(files[0]);
            }
    
            function updateInfos() {
                var infos = document.getElementById('infos');
                infos.textContent = "";
                for (var i = 0; i < myVideos.length; i++) {
                    infos.textContent += myVideos[i].name + " duration: " + myVideos[i].duration + '
    ';
                }
            }
    
        </script>

    上传之后可以看到如下结果:

    从这个例子里可以看到,已经可以成功的拿到时长的数据了,但是在真实的项目中如果每次都需要在html代码里加video标签,这会是一件很麻烦且不规范的事情。

    so ~

    html部分 可以优化一下,动态去创建节点。在现代浏览器中,可以使用带有非追加视频元素的URL API URL.createObjectURL()来加载文件的内容;

    URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。

        this.video = document.createElement('video')
        this.video.preload = 'metadata'
        this.video.src = URL.createObjectURL(file)

    获取视频第一帧

    方案一

    通过创建canvas标签,利用其drawImage() 方法在画布上绘制该视频,然后运用toDataURL方法转换canvas上的图片为base64格式,并将base64格式的图片作为video标签的poster属性。

    需要注意的是,由于canvas无法对跨域的图片进行操作,需要提前处理好跨域问题。

    核心实现代码如下:

    getVideoBase64(url) {
        return new Promise(function (resolve, reject) {
            let dataURL = '';
            let video = document.createElement("video");
            video.setAttribute('crossOrigin', 'anonymous');//处理跨域
            video.setAttribute('src', url);
            video.setAttribute('width', 400);
            video.setAttribute('height', 240);
            video.addEventListener('loadeddata', function () {
                let canvas = document.createElement("canvas")
                let width = video.width, //canvas的尺寸和图片一样
                let height = video.height;
                canvas.width = width;
                canvas.height = height;
                canvas.getContext("2d").drawImage(video, 0, 0, width, height); //绘制canvas
                dataURL = canvas.toDataURL('image/jpeg'); //转换为base64
                resolve(dataURL);
            });
        })
    }

    方案二

    可以选择使用第三方平台实现。七牛云、阿里云等云端存储平台功能强大,不仅具有海量的存储功能,平台封装的还有很多功能丰富的API。这次使用的是阿里云OSS,以OSS为例,说明一下视频截取方法。

    如存储在阿里云平台的视频名称为:

    http://a-image-demo.oss-cn-qingdao.aliyuncs.com/demo.mp4

    那么如果想要实现截取视频的某一帧其实很方便,只需在视频的url后面这样拼接即可:

    http://a-image-demo.oss-cn-qingdao.aliyuncs.com/demo.mp4?x-oss-process=video/snapshot,t_7000,f_jpg,w_800,h_600,m_fast

    获取文件类型

    拿文件类型相对来说比较简单,但是遵循万物皆可Function的原则,还是封装一下吧

      getFileType (fileName) {
        var exts = fileName.split('.');
        var ext = "";
        if (exts != undefined) {
            if (exts.length <= 1 && fileName.indexOf('=')>-1) {//直接输入上传到azure之后生成的文件地址
                console.log('输入是文件地址:', exts);
                return false
            } else {
                ext = exts[exts.length - 1];
                ext = ext.toLowerCase();
                return ext
            }
        } else {
          return false
        }
      }

    获取文件大小

      /**
       * [fileLengthFormat 格式化文件大小]
       * @param  {[int]} total [文件大小] Byte
       * @param  {[int]} n {1: "KB", 2: "MB", 3: "GB", 4: "TB"}
       * @return {[string]}       [带单位的文件大小的字符串]
       */
      fileLengthFormat(total, n) {
        var format;
        var len = total / (1024);
        if (len > 1000) {
            return this.fileLengthFormat(len, ++n)
        } else {
            switch (n) {
                case 1:
                    format = len.toFixed(2)
                    break;
                case 2:
                    format = len.toFixed(2)
                    break;
                case 3:
                    format = len.toFixed(2)
                    break;
                case 4:
                    format = len.toFixed(2)
                    break;
            }
            return +format;
        }
      }
    

    获取尺寸

    先展示部分伪代码,完整的代码可以戳下面的完整代码链接;

      video.onloadedmetadata = () => {
        window.URL.revokeObjectURL(this.video.src);
        let height = video.videoHeight
        let width = video.videoWidth
      }
    
  • 相关阅读:
    页面高度自适应方法(PC、移动端都适用)
    Axure 文本框去掉边框 富文本 粘贴文字图标
    Axure 文本框去掉边框 富文本 粘贴文字图标
    mui switch 点击事件不冒泡
    使用vue-router+vuex进行导航守卫(转)
    Layui select下拉框改变之 change 监听事件(转)
    jQuery获取节点和子节点文本的方法
    动态规划(3)——算法导论(18)
    动态规划(2)——算法导论(17)
    Base64编码
  • 原文地址:https://www.cnblogs.com/peijz/p/12750469.html
Copyright © 2020-2023  润新知