純前端獲取視頻第一幀、大小、尺寸、類型等

需求背景

最近有個視頻上傳的需求,須要對上傳上傳到OSS的視頻作一些限制,而且在上傳以前判斷,視頻的大小、尺寸、比例、時長等等。內心一直想着OSS能直接把視頻的相關信息返回;畢竟圖片是有不少信息返回的;
然而通過確認以後,發現屁都沒有……
那就只能本身寫了,百度了一下,並無特別全的方案,那就本身動手寫個吧。html

視頻加載基本介紹

在視頻/音頻(audio/video)加載過程當中,事件的觸發順序以下:git

  1. onloadstart (瀏覽器開始尋找指定資源)
  2. ondurationchange (視頻/音頻 的時長髮生變化時觸發)
  3. onloadedmetadata (指定視頻/音頻 的元數據加載後觸發)
  4. onloadeddata (當前幀的數據加載完成且尚未足夠的數據播放)
  5. onprogress (下載指定的視頻/音頻 時觸發)
  6. oncanplay (用戶能夠開始播放視頻/音頻 時觸發)
  7. oncanplaythrough (能夠正常播放且無需停頓和緩衝時觸發)

寫個小代碼

得到時長

找了一個相對好一點的方案,而後準備改巴改巴……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

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

相關文章
相關標籤/搜索