从HTML5视频中获取原始像素数据

时间:2012-08-26 13:22:58

标签: html5 video canvas

我想从视频元素中获取原始数据(TypedArray或其他内容)并使用JavaScript操作它们。

目前我创建了一个新画布,将视频绘制到画布中,然后获取图像数据。

ctx.drawImage(myVideo);
var data = ctx.getImageData(0, 0, w, h).data;

它工作正常,但它耗尽了CPU(将视频放到画布上并从画布复制回来)并且它会产生大量垃圾(每秒大约50 MB)。还有其他更简单的解决方案吗?如果我可以将自己的缓冲区传递给getImageData(...),那就太好了。

顺便说一句。使用WebGL绘制视频并从GPU加载它不会更快:( http://jsperf.com/getting-raw-data-from-video

3 个答案:

答案 0 :(得分:4)

请阅读

https://www.scirra.com/blog/76/how-to-write-low-garbage-real-time-javascript

因为您实际上没有显示任何代码,请提及浏览器或提供有关视频的信息(分辨率,FPS,编码),无法分辨为什么您的代码很慢或为什么它创建显示垃圾。使用Javasrcipt的实时视频效果可能会受到一些分辨率的限制。

以下是使用。的实时视频过滤的Mozilla示例。

https://developer.mozilla.org/samples/video/chroma-key/index.xhtml

如果不首先在<canvas>上放置视频帧,您将无法获得对视频数据的任何原始访问权限。但是,我相信这个操作应该是硬件加速,因为它发生在GPU内存中。从GPU下载像素,在Javascript中操作它们然后上传回显示内存可能是高分辨率的最慢步骤。

优化提示

答案 1 :(得分:1)

clearRect()是我想要的。

据我所知,在画布上上传图像会占用空间,但是clearRect()会删除画布上的所有内存。

我对JS代码所做的事情:

  1. 在下面的代码下方,我在视频标签上设置了流。有关更多网络摄像头信息,请参见https://www.kirupa.com/html5/accessing_your_webcam_in_html5.htm

  2. 我将间隔设置为一秒钟(每秒调用一次函数)以清除画布,然后绘制该帧上的流。

  3. 现在轮到您了。最小化视频或画布不会影响操作。现在,您可以随时在网络摄像头或视频上获取彩色图像。

这是工作代码:

注意:我发现此示例不适用于内置的Web查看器。此示例需要它自己的网页。

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta content="stuff, to, help, search, engines, not" name="keywords">
<meta content="What this page is about." name="description">
<meta content="Display Webcam Stream" name="title">
<title>Display Webcam Stream</title>
  
<style>
#container {
    margin: 0px auto;
    width: 500px;
    height: 375px;
    border: 10px #333 solid;
}
#videoElement {
    width: 500px;
    height: 375px;
    background-color: #666;
}
#canvas {
  background-color: #666;
}
</style>
</head>
  
<body>
    <video autoplay="true" id="videoElement"></video>
    <canvas id="canvas" onclick= canvasOnclick()></canvas>

<script>
var video = document.querySelector("#videoElement");
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
if (navigator.mediaDevices.getUserMedia) {       
    navigator.mediaDevices.getUserMedia({video: true})
  .then(function(stream) {
    video.srcObject = stream;
  })
  .catch(function(err0r) {
    console.log("Something went wrong!");
  });
}



var myVar = setInterval(intervalTimer, 1000);

function intervalTimer() {
  ctx.clearRect(0,0,400,400);
  ctx.drawImage(video,0,0,400,400);

}

//var data = ctx.getImageData(0, 0, w, h).data;
</script>
</body>
</html>

答案 2 :(得分:0)

canvas{display:none}可能有助于减少一些开销。画布仍然可供js访问。