最近有个视频上传的需求,须要对上传上传到OSS的视频作一些限制,而且在上传以前判断,视频的大小、尺寸、比例、时长等等。内心一直想着OSS能直接把视频的相关信息返回;毕竟图片是有不少信息返回的;
然而通过确认以后,发现屁都没有……
那就只能本身写了,百度了一下,并无特别全的方案,那就本身动手写个吧。html
在视频/音频(audio/video)加载过程当中,事件的触发顺序以下:git
找了一个相对好一点的方案,而后准备改巴改巴……github
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>
上传以后能够看到以下结果:web
从这个例子里能够看到,已经能够成功的拿到时长的数据了,可是在真实的项目中若是每次都须要在html代码里加video标签,这会是一件很麻烦且不规范的事情。canvas
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属性。ide
须要注意的是,因为canvas没法对跨域的图片进行操做,须要提早处理好跨域问题。post
核心实现代码以下:优化
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; } }
先展现部分伪代码,完整的代码能够戳下面的完整代码连接;
revokeObjectURL介绍
video.onloadedmetadata = () => { window.URL.revokeObjectURL(this.video.src); let height = video.videoHeight let width = video.videoWidth }
最后奉上完整的代码 ==> CalcVideo.js