首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >html5视频处理性能的优化

html5视频处理性能的优化
EN

Code Review用户
提问于 2014-01-17 14:32:02
回答 2查看 1.8K关注 0票数 7

我一直致力于html5帆布视频播放器与许多有趣的小附加和ui玩具,主要是一个色度键(绿色屏幕)的效果,使用户可以键入不同的颜色或范围的颜色,而视频播放。

在推荐的色度键方法中,我似乎遇到了一个障碍。它可以工作,但这是一个非常繁重的过程,如果用户在后台运行其他应用程序,那么cpu的负担就会达到视频看起来不稳定的程度。

下面是我为chroma键效果使用的简化代码:

代码语言:javascript
复制
   <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
        };

现场演示

希望能找到进一步优化这一性能的方法。

EN

回答 2

Code Review用户

回答已采纳

发布于 2014-01-20 17:28:50

在与ChrisW和你自己来回交流之后,我似乎发现了一个明显的错误

代码语言:javascript
复制
    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倍。

这一观察结合佳士得的常识观察得出如下结论:

代码语言:javascript
复制
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);
};
票数 5
EN

Code Review用户

发布于 2014-01-19 23:51:27

您的大部分代码是API调用。我感到惊讶的是,Javascript的运行速度竟然足够快(在我的旧笔记本电脑上,它没有使用Chrome浏览器)。

我将假设使用完全不同的API,例如用不同的编译语言编写插件(如果可能的话)是超出了这个问题的范围。

因此,我猜想唯一可能/有趣/相关的性能优化是在代码中实现的处理,即以下代码片段:

代码语言:javascript
复制
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:

代码语言:javascript
复制
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包含无符号数字不可能是负的,因此没有必要对大于或等于零的测试:

代码语言:javascript
复制
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;
    }
}

如果不使用临时变量,则如果先前的颜色值无法通过测试,则不需要将颜色值与数组中的颜色值相提并论,例如:

代码语言:javascript
复制
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;
    }
}

如果每次不取消对帧的引用,可能会更快:

代码语言:javascript
复制
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编译器已经在进行的优化。

票数 4
EN
页面原文内容由Code Review提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://codereview.stackexchange.com/questions/39476

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档