title: Reducing CPU usage of navigator.webkitGetUserMedia (Electron: DesktopCapturer)
body: <p>I'm using <code>navigator.webkitGetUserMedia</code> to capture screenshot of a window once every second by assigning the returned <code>stream</code> to a <code>&lt;video&gt;</code> and copying it to a <code>&lt;canvas&gt;</code> and saving the Buffer to file.</p>
  <p>The CPU usage in my application is consistently high and I've pinpointed it to this area.</p>
  <h1>Code</h1>
  <pre><code>// 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 &lt;video&gt;
    _video.src = window.URL.createObjectURL(stream);
  
    // Reference the stream locally
    localStream = stream;
  }
  
  function captureState() {
    var buffer,
      dataURL;
  
    // Draw &lt;video&gt; to &lt;canvas&gt; and convert to buffer (image data)
    _ctx.drawImage(_video, 0, 0);
    dataURL = _canvas.toDataURL('image/png');
    buffer = new Buffer(dataURL.split(&quot;,&quot;)[1], 'base64');
  
    // Create an image from the data
    fs.writeFileSync('screenshot.png', buffer);
  }
  
  // Capture state every second
  setInterval(function() {
    captureState();
  }, 1000);
  </code></pre>
  <p>This code my not run, it's a simplified version of what I have in my code to make it StackOverflow readable.</p>
  <h1>Things I've Tried</h1>
  <ol>
  <li><code>_video.pause()</code> and <code>_video.play()</code> when needed. Didn't seem to change CPU usage.</li>
  <li><code>_video.stop()</code>. This means I would have to get the stream again which causes a spike in CPU usage worse than keeping it open.</li>
  </ol>
  <p>My best lead right now is to change the frame rate by adding:</p>
  <pre><code>  optional: [
      { minFrameRate: 1 },
      { frameRate: 1 }
    ]
  </code></pre>
  <p>Extremely low frame rate would be fine. However, I haven't been able to determine if the <code>frameRate</code> setting works in this case. <a href="https://developer.mozilla.org/en/docs/Web/API/Navigator/getUserMedia" rel="nofollow noreferrer">The docs</a> don't have it listed and I don't have the newer <code>mediaDevices.getUserMedia</code> available.</p>
  <p>Is it possible to set extremely low frame rates (or any at all) for <code>navigator.webkitGetUserMedia</code>?</p>
  <p>Has anyone been able to reduce CPU usage of the stream in any other way?</p>
  <p>Any alternative methods of achieving the same goal (state capture on interval) would also be helpful.</p>
  <p>Thanks!</p>
  <p><strong>Side Note</strong></p>
  <p>This is in an Electron app on Windows using <a href="https://github.com/electron/electron/blob/master/docs/api/desktop-capturer.md" rel="nofollow noreferrer">DesktopCapturer</a> to get the <code>chromeMediaSourceId</code>.</p>
  <hr />
  <p><strong>Update on CPU Usage</strong></p>
  <ol>
  <li>Cost of running <code>stream</code>: 6% CPU Usage</li>
  <li>Calling <code>captureState</code> every 1000ms: 5% CPU Usage</li>
  </ol>
  <p>Total Current: 11%</p>
  <p>Currently working on reducing #2 based on the recommendations of Csaba Toth so far. I should be able to reduce <code>captureState</code> by changing how the canvas is captured. Will update when that's done.</p>
  <p>For #1, if I can't avoid capturing the video stream I'll have to just try to cap the total CPU usage at just over 6% by optimizing #2.</p>