从 HTML5 视频中获取原始像素数据
Posted
技术标签:
【中文标题】从 HTML5 视频中获取原始像素数据【英文标题】:Get raw pixel data from HTML5 video 【发布时间】:2012-08-21 06:17:10 【问题描述】:我想从视频元素中获取原始数据(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
【问题讨论】:
这是最简单的方法。您也许可以通过 WebGL 获得更多性能。您可以看到github.com/brianchirls/Seriously.js 是如何处理视频过滤器的。 嘿,谢谢你的链接。该库在片段着色器中编辑原始数据。但我需要从 JavaScript 编辑它:( 【参考方案1】:请阅读
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 中对其进行操作,然后上传回显存可能是高分辨率的最慢步骤。
优化提示
考虑跳帧(较低 FPS 的处理效果)
服务器端HTML5视频渲染Rendering HTML5 animation server-side?
【讨论】:
我的问题不是关于 Bowser,而是关于 W3C 规范。我给你看了代码。问题是,HTML5 画布上下文函数 getImageData 生成一个新的 ArrayBufferView,每个像素有 4 个字节。这就是我寻找其他解决方案的原因。 嘿,我正在获取对视频数据的原始访问权限 - 我什至编写了我如何做到这一点的代码...... 顺便说一句。 Mozilla 示例读取原始数据的方式与我相同(getImageData(...))。那里没有改进。 Chrome 实现了增量垃圾收集器,有助于快速创建对象;您还可以调整其他浏览器上的垃圾收集器设置。您仍然没有提及使用哪种浏览器消耗 50 MB / sec 以及使用哪种帧。是的 我更新了问题。对于原始视频数据访问,我的意思是直接访问 video.getImageData() ,而不是先将其传送到画布上。如您所见, getImageData() 是当前操作数据的唯一方法。但是你是对的,API 没有让你能够回收你自己的缓冲区,但它也不应该创建一个新的缓冲区。您确定垃圾来自像素数据而不是来自您的其他代码吗?也许您在 Javascript 中保留了像素数据指针的副本(范围定义错误),并且像素数据引用永远不会被回收。【参考方案2】:clearRect() 是我认为你正在寻找的。p>
据我所知,在画布上上传图像会占用空间,但 clearRect() 会删除画布上的所有内存。
我在 JS 代码上做了什么:
在下面的代码中,我在视频标签上设置了一个流。有关更多网络摄像头信息,请参阅https://www.kirupa.com/html5/accessing_your_webcam_in_html5.htm。
我设置一秒的时间间隔(每秒调用一次函数)来清除画布,然后在该帧上绘制流。
现在轮到你了。最小化视频或画布应该对做什么没有影响。现在您可以随时抓取网络摄像头或视频上的像素颜色。
这是工作代码:
注意:我发现此示例不适用于内置 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>
【讨论】:
谢谢!但我不想在 Canvas 上绘制视频。我想获取像素数据(当前视频帧的每个像素的红色、绿色和蓝色的值),所以我可以用我的代码循环像素,计算平均颜色等。【参考方案3】:canvasdisplay:none
可能有助于减少一些开销。 js 仍然可以访问 Canvas。
【讨论】:
谢谢!我用 JS 做画布,并没有将它们添加到文档中。以上是关于从 HTML5 视频中获取原始像素数据的主要内容,如果未能解决你的问题,请参考以下文章
OSX 上的 AVFoundation:来自视频的 OpenGL 纹理,无需访问像素数据