首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >降低navigator.webkitGetUserMedia (电子: DesktopCapturer)的CPU利用率

降低navigator.webkitGetUserMedia (电子: DesktopCapturer)的CPU利用率
EN

Stack Overflow用户
提问于 2016-07-07 10:46:33
回答 1查看 1.6K关注 0票数 3

我使用navigator.webkitGetUserMedia每秒钟捕获一次窗口的屏幕快照,方法是将返回的stream分配给<video>,并将其复制到<canvas>中,并将缓冲区保存到文件中。

我的应用程序中的CPU使用率一直很高,我已经将其定位到了这一领域。

代码

代码语言:javascript
复制
// Initialize the video, canvas, and ctx
var localStream,
  _video = document.querySelector('#video'),
  _canvas = document.querySelector('#canvas'),
  _ctx = _canvas.getContext('2d'),
  sourceName = 'my-window-id';

// Load the stream from navigator.webkitGetUserMedia
navigator.webkitGetUserMedia({
  audio: false,
  video: {
    mandatory: {
      chromeMediaSource: 'desktop',
      chromeMediaSourceId: sourceName,
      minWidth: 1920,
      maxWidth: 1920,
      minHeight: 1080,
      maxHeight: 1080
    }
  }
}, gotStream, getUserMediaError);

function gotStream(stream) {
  // Use the stream in our <video>
  _video.src = window.URL.createObjectURL(stream);

  // Reference the stream locally
  localStream = stream;
}

function captureState() {
  var buffer,
    dataURL;

  // Draw <video> to <canvas> and convert to buffer (image data)
  _ctx.drawImage(_video, 0, 0);
  dataURL = _canvas.toDataURL('image/png');
  buffer = new Buffer(dataURL.split(",")[1], 'base64');

  // Create an image from the data
  fs.writeFileSync('screenshot.png', buffer);
}

// Capture state every second
setInterval(function() {
  captureState();
}, 1000);

这段代码我没有运行,它是我代码中的一个简化版本,以使它具有StackOverflow可读性。

我试过的东西

  1. _video.pause()_video.play()在需要的时候。似乎没有改变CPU的使用。
  2. _video.stop()。这意味着我将不得不再次获得流,这将导致CPU使用率的激增,而不是保持其打开。

我现在最好的方法是改变帧速率,增加:

代码语言:javascript
复制
  optional: [
    { minFrameRate: 1 },
    { frameRate: 1 }
  ]

极低的帧速率会很好。但是,在这种情况下,我还无法确定frameRate设置是否有效。医生们没有列出它,我也没有新的mediaDevices.getUserMedia可用。

是否可以为navigator.webkitGetUserMedia设置极低的帧速率(或任何帧速率)

是否有人能够以任何其他方式减少流的CPU使用量?

实现相同目标的任何替代方法(间隔上的状态捕获)也会有帮助。

谢谢!

边注

这是在Windows上的一个电子应用程序中,使用DesktopCapturer获取chromeMediaSourceId

关于CPU使用的更新

  1. 运行stream的成本: 6%的CPU使用率
  2. 每1000 CPU调用一次captureState:5%的CPU使用率

总电流: 11%

目前正在根据Csaba Toth迄今为止的建议减少#2。我应该能够通过改变画布捕获的方式来减少captureState。会在做完后更新。

对于#1,如果我无法避免捕获视频流,我将不得不尝试通过优化#2将总的CPU使用率限制在略高于6%。

EN

回答 1

Stack Overflow用户

发布于 2016-07-11 03:09:17

这里有一些不必要的base64编码和操作,如何获取数据是很奇怪的:

代码语言:javascript
复制
dataURL = _canvas.toDataURL('image/png');
buffer = new Buffer(dataURL.split(",")[1], 'base64');

看看QR解码器是如何访问图像的:https://github.com/bulldogearthday/booths/blob/master/scripts/qrdecoder.js#L1991

代码语言:javascript
复制
var canvas_qr = document.getElementById("qr-canvas");
var context = canvas_qr.getContext('2d');
qrcode.width = canvas_qr.width;
qrcode.height = canvas_qr.height;
qrcode.imagedata = context.getImageData(0, 0, qrcode.width, qrcode.height);

(软件的另一面在前面的画布上做了一个drawImage )。现在的任务是找到一种方法,它不会不必要地将PNG数据转换为base64,然后对其进行解码。我看到在任何地方都建议使用这种URI编码,因为它的行数较少。但就性能而言,必须的编码/解码阶段是不可取的。1920x1080PNGs很大,不适合base64内嵌。由于您是在nodejs中,所以尝试使用https://github.com/niegowski/node-pngjs或类似的库来保存图像数据。

在空间和时间之间总是有一种权衡,所以如果时间真的与较低的压缩有关,那么您可以拥有更高的性能:https://github.com/wheany/js-png-encoder

这里有一个折衷方案,因为base64 URI编码示例利用了浏览器的本机(C++,快速) png编码,然后执行不必要的base64 encodeing+decoding。节点pngjs将在JS域执行PNG编码,这可能不像浏览器的内部编码那样具有性能。最好是找到一种方法来利用浏览器的编码,而不需要base64。

较早的建议

根据您显示的内容,我认为您的主要问题是在gotStream中执行gotStream和其他操作。

这里是我的一个渐进Web,它也执行QR代码扫描:https://github.com/bulldogearthday/booths/blob/master/scripts/app.js注意到,在"gotStream“(在我的例子中是https://github.com/bulldogearthday/booths/blob/master/scripts/app.js#L67)中,我只将流连接到画布上。

我的情况更简单,因为我不需要强制执行大小(我希望您不要硬连接那些屏幕大小像素数),但我也定期执行处理(QR代码扫描尝试,每500毫秒)。我最初使用的是计时器,但在迭代/滴答之后就停止了工作,所以从技术上讲,我只发出一个超时,每次碰到它,我就重新发出一个新的超时。参见初始超时https://github.com/bulldogearthday/booths/blob/master/scripts/app.js#L209和定期重新发行:https://github.com/bulldogearthday/booths/blob/master/scripts/app.js#L231

正如您所看到的,我做“繁重工作”的唯一地方是在app.scanQRCode中,它每秒只发生两次。在这里,我处理画布的内容:https://github.com/bulldogearthday/booths/blob/master/scripts/app.js#L218

我建议你用这种方式重组你的代码。所以设置一个计时器,每秒钟滴答一次,或者像我一样重新发布超时。然后执行该部分中的capture+save。希望这将减轻CPU负载,尽管每秒编码一次1920x1080 PNG可能会给CPU带来压力(会有PNG编码)。

(这是有益的,如果你想要个人图像。如果你想最终得到一个视频,那么我会尝试按照你的建议执行1SFPS视频,直接捕获视频流而不是单个图像。但是对于CPU负载,我的建议应该有助于IMHO。)

在自述文件(https://github.com/bulldogearthday/booths)中,您可以看到getUserMedia的主要来源之一:https://github.com/samdutton/simpl/blob/gh-pages/getusermedia/sources/js/main.js

我不会摆弄发行.play().pause()之类的东西。事实上,我的代码一直等到它收到播放开始的信号(默认情况下,至少对摄像机启动):document.getElementById('qrVideo').addEventListener('playing', app.saveVideoSize, false);https://github.com/bulldogearthday/booths/blob/master/scripts/app.js#L67,我的意图是,如果可能的话,不要用任何东西干扰自然过程。在我的例子中,我用温和的方式检测到视频大小。查看DesktopCapturer,他们也不会在自述的https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md中在gotStream中执行任何额外的操作,理想情况下,您只需将视频流与画布连接起来。

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

https://stackoverflow.com/questions/38243490

复制
相关文章

相似问题

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