18

我想从视频元素中获取原始数据(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

4

3 回答 3

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 https://developer.mozilla.org/en-US/docs/Web/API/Canvas_API/Manipulating_video_using_canvas

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

优化提示

于 2012-09-20T21:59:01.490 回答
2

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>

于 2018-06-21T20:07:22.533 回答
0

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

于 2019-07-12T08:17:16.007 回答