HTML5:使用Canvas實時處理Video

(點擊上方,可快速關注)

結合HTML5下的video和canvas的功能,你可以實時處理影片數據,為正在播放的影片添加各種各樣的視覺效果。本教程演示如何使用JavaScript代碼做到chroma-keying特效(也被稱為「綠色螢幕效應」)。

請看這個實例:https://developer.mozilla.org/samples/video/chroma-key/index.xhtml

文檔內容

本文使用的XHTML文檔如下所示。

<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=“http://www.w3.org/1999/xhtml”>
<head>
<style>
body {
background: black;
color:#CCCCCC;
}
#c2 {
background-image: url(foo.png);
background-repeat: no-repeat;
}
div {
float: left;
border :1px solid #444444;
padding:10px;
margin: 10px;
background:#3B3B3B;
}
</style>
<script type=“text/javascript;version=1.8” src=“main.js”></script>
</head>

<body onload=“processor.doLoad()”>
<div>
<video id=“video” src=“video.ogv” controls=“true”/>
</div>
<div>
<canvas id=“c1” width=“160” height=“96”/>
<canvas id=“c2” width=“160” height=“96”/>
</div>
</body>
</html>

以上代碼關鍵部分如下:

1.創建了兩個canvas元素,ID分別為c1和c2。c1用於顯示當前幀的原始影片,c2是用來顯示執行chroma-keying特效後的影片;c2預加載了一張靜態圖片,將用來取代影片中的背景色部分。

2.JavaScript代碼從main.js文件導入;這段腳本使用JavaScript 1.8的特性,所以在導入腳本時,第22行中指定了版本。

3.當網頁加載時,main.js中的processor.doLoad()方法會運行。

JavaScript代碼

main.js中的JS代碼包含三個方法。

初始化chroma-key

doLoad()方法在XHTML文檔初始加載時調用。這個方法的作用是為chroma-key處理代碼準備所需的變量,設置一個事件偵聽器,當用戶開始播放影片時我們能檢測到。

doLoad: function() {
this.video = document.getElementById(“video”);
this.c1 = document.getElementById(“c1”);
this.ctx1 = this.c1.getContext(“2d”);
this.c2 = document.getElementById(“c2”);
this.ctx2 = this.c2.getContext(“2d”);
let self = this;
this.video.addEventListener(“play”, function() {
self.width = self.video.videoWidth / 2;
self.height = self.video.videoHeight / 2;
self.timerCallback();
}, false);
},

這段代碼獲取XHTML文檔中video元素和兩個canvas元素的引用,還獲取了兩個canvas的圖形上下文的引用。這些將在我們做到chroma-keying特效時使用。

addEventListener()監聽video元素,當用戶按下影片上的播放按鈕時被調用。為了應對用戶回放,這段代碼獲取影片的寬度和高度,並且減半(我們將在執行chroma-keying效果時將影片的大小減半),然後調用timerCallback()方法來啟動影片捕捉和視覺效果計算。

定時器回調

定時器回調函數在影片開始播放時被調用(當「播放」事件發生時),然後負責自身周期調用,為每一幀影片做到keying特效。

timerCallback: function() {
if (this.video.paused || this.video.ended) {
return;
}
this.computeFrame();
let self = this;
setTimeout(function () {
self.timerCallback();
}, 0);
},

回調函數首先檢查影片是否正在播放;如果沒有,回調函數不做任何事並立即返回。

然後調用computeFrame()方法,該方法對當前影片幀執行chroma-keying特效。

回調函數做的最後一件事就是調用setTimeout(),來讓它自身盡快地被重新調用。在真實環境中,你可能會基於影片的幀率來設置調用頻率。

處理影片幀數據

computeFrame()方法,如下所示,實際上負責抓取每一幀的數據和執行chroma-keying特效。

computeFrame: function() {
this.ctx1.drawImage(this.video, 0, 0, this.width, this.height);
let frame = this.ctx1.getImageData(0, 0, this.width, this.height);
let l = frame.data.length / 4;

for (let i = 0; i < l; i++) {
let r = frame.data[i * 4 + 0];
let g = frame.data[i * 4 + 1];
let b = frame.data[i * 4 + 2];
if (g > 100 && r > 100 && b < 43)
frame.data[i * 4 + 3] = 0;
}
this.ctx2.putImageData(frame, 0, 0);
return;
}

當它被調用後,video元素將顯示最近的影片幀數據,如下所示:

在第2行,影片幀被復制到第一個canvas ctx1的圖形上下文中,高度和寬度值指定為我們之前保存的幀大小的一半。注意,您可以通過傳遞video元素到繪圖上下文的drawImage()方法來繪制當前影片幀。其結果是:

第3行代碼通過調用第一個canvas上下文的getImageData()方法,來獲取原始圖像數據當前影片幀的一個副本。它提供了原始的32位像素圖像數據,這樣我們就能夠進行操作。第4行代碼通過將幀圖像數據的總長度除以4,來計算圖像的總像素數。

第6行代碼循環掃描所有像素,獲取每個像素的紅、綠、藍值,同時和預定義的背景色進行比較,這些背景色將用foo.png中導入的背景圖像替換。

被檢測成背景的每一個像素,將它的alpha值替換為零,表明該像素是完全透明的。結果,最終的圖像背景部分是100%透明的,這樣在第13行代碼,把它被繪制到目標的上下文中時,效果是內容疊加到靜態背景上。

由此產生的圖像看起來像這樣:

在影片播放時反復這樣做,這樣一幀接一幀處理,呈現出chroma-key的特效。

請看這個實例:https://developer.mozilla.org/samples/video/chroma-key/index.xhtml



前端大全
微信號:FrontDev

打造東半球最好的 前端技術 微信號

——–—————–————-

商務合作QQ:2302462408
投稿網址:top.jobbole.com

閱讀原文


關於作者:
分享Web前端相關的技術文章、工具資源、精選課程、熱點資訊

微信號:FrontDev