我一直致力于html5帆布视频播放器与许多有趣的小附加和ui玩具,主要是一个色度键(绿色屏幕)的效果,使用户可以键入不同的颜色或范围的颜色,而视频播放。
在推荐的色度键方法中,我似乎遇到了一个障碍。它可以工作,但这是一个非常繁重的过程,如果用户在后台运行其他应用程序,那么cpu的负担就会达到视频看起来不稳定的程度。
下面是我为chroma键效果使用的简化代码:
<video id="sourceVid" controls="true">
<source src="http://s3.amazonaws.com/dfc_attachments/public/documents/3185373/AAA.webm" />
</video>
<canvas id="hCanvas"></canvas>
<canvas id="dCanvas"></canvas>
<script type="text/javascript">
var doc = document;
var sourceVid = doc.getElementById("sourceVid");
var hCanvas = doc.getElementById("hCanvas");
var dCanvas = doc.getElementById("dCanvas");
var hContext = hCanvas.getContext("2d");
var dContext = dCanvas.getContext("2d");
sourceVid.addEventListener('loadeddata', function() {
hCanvas.setAttribute('width', sourceVid.offsetWidth);
dCanvas.setAttribute('width', sourceVid.offsetWidth);
hCanvas.setAttribute('height', sourceVid.offsetHeight);
dCanvas.setAttribute('height', sourceVid.offsetHeight);
}, false);
sourceVid.addEventListener('play', function() {
runAnalysis();
});
var runAnalysis = function() {
if (sourceVid.paused || sourceVid.ended) {
return
}
frameFix();
if (window.requestAnimationFrame) {
requestAnimationFrame(runAnalysis);
} else {
setTimeout(runAnalysis, 0);
}
};
var frameFix = function() {
hContext.drawImage(sourceVid, 0, 0, sourceVid.videoWidth, sourceVid.videoHeight);
var frame = hContext.getImageData(0, 0, sourceVid.videoWidth, sourceVid.videoHeight);
var length = frame.data.length;
for (var i = 0; i < length; i++) {
var r = frame.data[i * 4 + 0];
var g = frame.data[i * 4 + 1];
var b = frame.data[i * 4 + 2];
if (g >= 0 && g < 100 && r >= 0 && r < 100 && b >= 0 && b < 100) {
frame.data[i * 4 + 3] = 0;
}
}
dContext.putImageData(frame, 0, 0);
return
};希望能找到进一步优化这一性能的方法。
发布于 2014-01-20 17:28:50
在与ChrisW和你自己来回交流之后,我似乎发现了一个明显的错误
var frameFix = function() {
hContext.drawImage(sourceVid, 0, 0, sourceVid.videoWidth, sourceVid.videoHeight);
var frame = hContext.getImageData(0, 0, sourceVid.videoWidth, sourceVid.videoHeight);
var length = frame.data.length;
for (var i = 0; i < length; i++) {
var r = frame.data[i * 4 + 0];
var g = frame.data[i * 4 + 1];
var b = frame.data[i * 4 + 2];
if (g >= 0 && g < 100 && r >= 0 && r < 100 && b >= 0 && b < 100) {
frame.data[i * 4 + 3] = 0;
}
}
dContext.putImageData(frame, 0, 0);
return
};因为在frame.data中,每个像素有4个数据点,您只需要达到frame.data.length / 4,这将使您的代码速度提高4倍。
这一观察结合佳士得的常识观察得出如下结论:
var frameFix = function()
{
hContext.drawImage(sourceVid, 0, 0, sourceVid.videoWidth, sourceVid.videoHeight);
var frame = hContext.getImageData(0, 0, sourceVid.videoWidth, sourceVid.videoHeight),
data = frame.data,
length = data.length, i;
for (i = 0; i < length; i += 4)
if (data[i] < 100 && data[i + 1] < 100 && data[i + 2] < 100)
data[i + 3] = 0;
dContext.putImageData(frame, 0, 0);
};发布于 2014-01-19 23:51:27
您的大部分代码是API调用。我感到惊讶的是,Javascript的运行速度竟然足够快(在我的旧笔记本电脑上,它没有使用Chrome浏览器)。
我将假设使用完全不同的API,例如用不同的编译语言编写插件(如果可能的话)是超出了这个问题的范围。
因此,我猜想唯一可能/有趣/相关的性能优化是在代码中实现的处理,即以下代码片段:
for (var i = 0; i < length; i++) {
var r = frame.data[i * 4 + 0];
var g = frame.data[i * 4 + 1];
var b = frame.data[i * 4 + 2];
if (g >= 0 && g < 100 && r >= 0 && r < 100 && b >= 0 && b < 100) {
frame.data[i * 4 + 3] = 0;
}
}也许你可以不用乘以4:
length *= 4;
for (var i = 0; i < length; i += 4) {
var r = frame.data[i];
var g = frame.data[i + 1];
var b = frame.data[i + 2];
if (g >= 0 && g < 100 && r >= 0 && r < 100 && b >= 0 && b < 100) {
frame.data[i + 3] = 0;
}
}ImageData包含无符号数字不可能是负的,因此没有必要对大于或等于零的测试:
length *= 4;
for (var i = 0; i < length; i += 4) {
var r = frame.data[i];
var g = frame.data[i + 1];
var b = frame.data[i + 2];
if (g < 100 && r < 100 && b < 100) {
frame.data[i + 3] = 0;
}
}如果不使用临时变量,则如果先前的颜色值无法通过测试,则不需要将颜色值与数组中的颜色值相提并论,例如:
length *= 4;
for (var i = 0; i < length; i += 4) {
if (frame.data[i] < 100 && frame.data[i + 1] < 100 && frame.data[i + 2] < 100) {
frame.data[i + 3] = 0;
}
}如果每次不取消对帧的引用,可能会更快:
length *= 4;
var data = frame.data;
for (var i = 0; i < length; i += 4) {
if (data[i] < 100 && data[i + 1] < 100 && data[i + 2] < 100) {
data[i + 3] = 0;
}
}这些更改可能不会影响性能:根据浏览器的不同,它们可能是Javascript编译器已经在进行的优化。
https://codereview.stackexchange.com/questions/39476
复制相似问题