移動端canvas實現視頻截取圖片并下載為gif實例調研說明

需求說明

前端實現視頻截取片段,并轉換為gif圖片下載到本地

參考文檔

HTML5 CSS3 誘人的實例 :模仿優酷視頻截圖功能
github antimatter15

結果說明

純前端通過canvas截幀并可以保存為gif形式當前在移動端chrome、safari瀏覽器支持較好。

demo展示

圖片截圖
視頻截圖

canvas截圖圖片實例

  • 截取圖片
    在截取視頻之前,首先進行了截取圖片的嘗試。截取圖片或者視頻主要使用了canvas的CanvasRenderingContext2D.drawImage()MDN說明該函數可以在canvas畫布上繪制圖像,繪制圖像后通過HTMLCanvasElement.toDataURL() 函數返回一個包含圖片展示的dataUrlMDN說明
this.canvas = document.createElement("canvas”);
 this.ctx = this.canvas.getContext("2d”);
 this.ctx.drawImage( this.img,0,0,this.Width, this.Height,0,0,this.Width,this.Height);
let dataUrl = this.canvas.toDataURL("image/png”);
  • 轉成gif下載
    轉成gif下載主要使用了jsgif中的如下代碼,引入了 如下JS文件
<script type="text/javascript" src="LZWEncoder.js"></script>
<script type="text/javascript" src="NeuQuant.js"></script>
<script type="text/javascript" src="GIFEncoder.js"></script>
<script type="text/javascript" src="b64.js"></script>

QQ20171121-192529@2x.png

這里需要注意的是encoder.addFrame(context);中傳遞的context參數,文檔中說或者是canvas元素,或者是imageData形式。那么imageData.data類型要怎么獲取到呢?通過函數CanvasRenderingContext2D.getImageData()MDN說明,該函數可以返回一個imageDataMDN說明對象,ImageData.data是[Uint8ClampedArray]類型,描述了一個一維數組,包含以 RGBA 順序的數據,數據使用
(包含)的整數表示。將ImageData.data傳入encoder.addFrame即可,這樣就實現了canvas截圖后并將其轉成gif形式。

let context = this.ctx.getImageData(0,0,this.Width,this.Height).data
            var encoder = new GIFEncoder();
           encoder.setRepeat(0); //0  -> loop forever
                                                  //1+ -> loop n times then stop
            encoder.setDelay(10); //這里單張圖片并不需要用到,用于設置幀數間隔時間
            encoder.start();
            encoder.setSize(640, 430); //此處應和canvas獲得的圖片尺寸一致
            encoder.addFrame(context, true);            
            encoder.finish();
            encoder.download("download.gif");
        
  • gif下載
    單張圖片是完全沒有必要下載成gif的,這個主要是為了視頻截取而準備,在GIFEncoder.js中,主要采用如下代碼實現了圖片下載。
ar templink = document.createElement("a");
templink.download=filename;//filename = ‘download.gif'
templink.href= URL.createObjectURL(new Blob([new Uint8Array(out.bin)], {type : "image/gif" } ))
console.log(templink)
templink.click()

在上面代碼中templink得到的是如下一個超鏈接標簽,在chrome中執行click()會直接下載該文件,safari則會打開一個新的頁面
<a download="download.gif" href="blob:http://xxxxxx:3023/12465504-7074-466a-8828-29ee44848612"></a>

上面創建下載鏈接主要是采用了URL.createObjectURL()對象MDN說明

MDN上說該靜態方法會創建一個 [DOMString]其中包含一個表示參數中給出的對象的URL。這個 URL 的生命周期和創建它的窗口中的 [document]綁定。這個新的URL 對象表示指定[File]對象或 [Blob]對象

Blob對象表示不可變的類似文件對象的原始數據。Blob表示不一定是JavaScript原生形式的數據。 File 接口基于Blob,繼承了 blob的功能并將其擴展使其支持用戶系統上的文件對象

這里對Blob的理解并不深刻,上面獲取的href地址從測試結果來看,uc、QQ等瀏覽器是不支持其打開預覽下載的。所以這個合成gif并下載的功能在chrome和safari可支持使用。

canvas截取視頻實例

截取視頻和截取圖片的區別在于視頻是多次截取拼成gif圖片,在截圖、轉成GIF、下載與截取圖片所用核心代碼基本一致,差別只在于視頻需要設置起始于結束時間,該時間段內setInterval循環繪制canvas圖片,循環繪制后,生成imageData.data的數組,該數組循環調用encoder.addFrame(context, true)方法。
事件主要代碼如下:

var draw = new drawVideo($('video')[0]);
document.getElementById('j_begin').addEventListener('click',()=>{
    document.getElementById('video').currentTime = startTime;
    document.getElementById('video').play();
    var time = setInterval(()=>{
        draw.paint();
        document.getElementById('video').play(); //每次繪制完需要將視頻播放

        if(document.getElementById('video').currentTime > endTime){//超過當前結束時間停止繪制canvas
            console.log('stop');
            clearInterval(time);

            var encoder = new GIFEncoder();
            encoder.setRepeat(0); //0  -> loop forever
            //1+ -> loop n times then stop
            encoder.setDelay(300); //這個時間的設置會影響gif展現時的速度
            encoder.start();
            encoder.setSize(1280, 720);//此處高度應為視頻寬高
            draw.result.forEach((ele,index)=>{
                encoder.addFrame(ele, true);//循環添加canvas的每一幀合成gif
            })
            encoder.finish();
            encoder.download("download.gif");


        }
        
    },1500);//1500秒為循環時間,如果時間設置太短看,手機上卡頓特別明顯,時間設置太長,生產的gif不流暢。
    
    
},false)
最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容