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

贾蓁
• 阅读 17165

需求背景

最近有个视频上传的需求,需要对上传上传到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 + '\n';
            }
        }

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

OSS视频截帧文档,戳这里~

参考文章

获取文件类型

拿文件类型相对来说比较简单,但是遵循万物皆可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;
    }
  }

获取尺寸

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

  video.onloadedmetadata = () => {
    window.URL.revokeObjectURL(this.video.src);
    let height = video.videoHeight
    let width = video.videoWidth
  }

最后奉上完整的代码 ==> CalcVideo.js

点赞
收藏
评论区
推荐文章
Easter79 Easter79
3年前
tp6+FFMpeg实现视频水印及大小剪切
之前项目中用到上传视频时,需要获取视频大小,视频第一帧及给视频添加水印问题,找了很多资料,结合在项目中的实际运用,在此记录一下。1.FFMpeg安装1.下载扩展网上可以找到,我这里放到百度云盘链接:百度云盘下载(https://www.oschina.net/action/GoToL
Wesley13 Wesley13
3年前
javaCV
  最近有视频处理的需求,自己调研javaCV。  官网没有详细的API,各种轮子翻遍了也没找到几个有用的,以下是自己整理一些视频处理功能:截取视频指定帧生成gif,将图片旋转指定度,截取视频指定帧保存为指定格式的图片(图片保存在视频同文件夹下),_调整视频清晰度(只能降低),_视频转音频__。  先上代码。packagecom.ric
Stella981 Stella981
3年前
Javascript判断Video视频播放、暂停、结束完成及获取长度事件监听处理
在日常应用场景中,可能会遇到这么一个情况,需要判断用户是否完整的观看完了一部视频,在这个场景中,和视频相关的事件大体涉及到几个部分,获取视频长度,视频开始播放,暂停播放和播放结束,下面来看下如何通过JavaScript来监听获取视频的这几种状态。html页面视频标签大体如下:<video id\"video" controls\"controls
Wesley13 Wesley13
3年前
Vitis尝鲜(四)
公众号不允许上传不是原创视频,所以只能上传到B站了,以后相关的视频还会同步更新到B站。主要包括:1、InstallVitis2019.2onLinuxUbuntu2、GettingStartedwithEDGEZYNQSoCFPGAkitusingVITISSoftwarePlatform2019.23、
Stella981 Stella981
3年前
Python骚操作:利用Python获取摄像头并实时控制人脸!
实现流程从摄像头获取视频流,并转换为一帧一帧的图像,然后将图像信息传递给opencv这个工具库处理,返回灰度图像(就像你使用本地静态图片一样)程序启动后,根据监听器信息,使用一个while循环,不断的加载视频图像,然后返回给opencv工具呈现图像信息。创建一个键盘事件监听,按下"d"键,则开始执行面部匹配,并进行面具加
Stella981 Stella981
3年前
Qt音视频开发27
一、前言最近业余时间主要研究音视频开发这块,前面的文章写了好多种视频监控内核,一旦将这些内核搞定以后,视频监控的相关功能水到渠成。做视频监控系统,绕不过onvif这玩意,这玩意主要就是为了统一一个大概的标准,能够对各个厂家的监控设备进行常用的一些操作,比如搜索、获取信息、云台控制、事件订阅、抓拍图片等,如果没有这个规范,那么各个厂家都各自为政,
Stella981 Stella981
3年前
HTML5 file API加canvas实现图片前端JS压缩并上传
一、图片上传前端压缩的现实意义对于大尺寸图片的上传,在前端进行压缩除了省流量外,最大的意义是极大的提高了用户体验。这种体验包括两方面:1.由于上传图片尺寸比较小,因此上传速度会比较快,交互会更加流畅,同时大大降低了网络异常导致上传失败风险。2.最最重要的体验改进点:省略了图片的再加工成本。很多网站的图片上传功能都会对图片的大小进
Wesley13 Wesley13
3年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
Stella981 Stella981
3年前
Javascript验证上传图片大小[前台处理]
需求分析:在做上传图片的时候,如果不限制上传图片大小,后果非常的严重。那么我们怎样才可以解决一个棘手的问题呢?有两种方式:1)后台处理:也就是AJAXPOST提交到后台,把图片上传到服务器上,然后获得该图片大小做处理。2)前台处理:也就是利用Javascript获取该图片大小。显然第一种方式,很不好。因为需要把文件先上传到
京东云开发者 京东云开发者
6个月前
记录一次「OSS上传文件的前置处理机制」实例剖析
作者:京东物流陈雨引言在云计算环境中,对象存储服务(OSS)是一种提供存储和访问任意类型数据(如网站内容、企业备份数据、游戏、IoT设备数据等)的服务,支持从任何地点、任何时间访问数据。在很多应用场景中,用户需要上传文件到OSS,这可能包括图片、视频、文档
美凌格栋栋酱 美凌格栋栋酱
5个月前
Oracle 分组与拼接字符串同时使用
SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(