screenshot-desktop icon indicating copy to clipboard operation
screenshot-desktop copied to clipboard

Windows Performance Improvements

Open jespertheend opened this issue 5 years ago • 10 comments

Hi, I'd like to use this to capture my screen and send the average color to my hue lights so the color of the lights are synced with what is displayed on the screen. But in order for this to work, taking screenshots should be somewhat fast. So far I measured about 300ms before the screenshot() promise is resolved. This was on a somewhat decent windows PC. I was hoping to get a framerate of at least about 10fps, though 3fps should also be fine to be honest. But having a lower latency would be nice. Is there anything that could be done to improve the performance a bit? I wanted to have a look at the code to see if I could find anything but I think most of the code is inside screenCapture_1.3.2.bat. Is the source code of this file available somewhere?

jespertheend avatar Sep 13 '19 20:09 jespertheend

Hi @jespertheend

The code that handles the functionality for Windows can be found at https://github.com/bencevans/screenshot-desktop/tree/master/lib/win32

I suspect if there's any improvements in speed it would probably be in the https://github.com/bencevans/screenshot-desktop/blob/master/lib/win32/screenCapture_1.3.2.bat file although haven't run a tests on where the performance lag actually comes from.

bencevans avatar Sep 20 '19 16:09 bencevans

Oh hah, for some reason I was expecting screenCapture_1.3.2.bat to be binary. I got confused with .dll files, weird. Alright nice, I'll check it out and do some profiling.

I think the main reason for the long execution time is that the screenshot is being written to disk, then read by nodejs into memory, and then deleted. I'll try to figure out if there's a way to pipe it from the bat file to nodejs.

jespertheend avatar Sep 20 '19 18:09 jespertheend

That'd be fantastic!

bencevans avatar Sep 21 '19 17:09 bencevans

@G7495x I have a routine repeating every 2s. My task manager reports up to 3MB/S disk usage. Just reporting... https://github.com/bencevans/screenshot-desktop/issues/161#issue-589753434

bencevans avatar May 30 '20 12:05 bencevans

Would you guys be interested in a PR with a powershell based solution? I've got something written up taking about 15-20ms by piping screenshots straight through stdout.

(Powershell isn't a requirement, I'm just not well versed in .NET)

sxxov avatar Aug 05 '21 11:08 sxxov

That sounds like a big improvement. Yes, very interested.

bencevans avatar Aug 05 '21 12:08 bencevans

I looked around & noticed that https://github.com/bencevans/screenshot-desktop/pull/193 is in the pipeline. A big refactor to Powershell would probably not be a good idea xd. I could publish my code elsewhere & maybe others may adapt it to be used in .NET. It shouldn't be too hard as it's just a matter of piping & not corrupting binary STDOUTs. (:

EDIT: Just did some more testing. the 15-20ms figure I'd got inside powershell, but the overhead from node communication adds on top a few hundred ms (200-300). Back to the drawing board I guess xd

sxxov avatar Aug 05 '21 14:08 sxxov

The windows-ffi library I just put together works well for me for fast screenshot-taking. (StackOverflow post)

It uses ffi-napi to make the Windows API calls necessary to take a screenshot, and then reads from the Buffer object to retrieve the pixel data.

Here are the timings I got:

  • Full-screen (2560x1440), all windows (ie. "desktop" window): ~80ms
  • Full-screen (2560x1440), single window: ~20ms
  • Region (700x200), all windows (ie. "desktop" window): ~50ms
  • Region (700x200), single window: ~4ms

Venryx avatar Sep 05 '21 13:09 Venryx

If anyone's still wondering, I've developed my research into a full package available from npm/github — windows-ss. It uses edge-js & C# (managed to learn it, was surprisingly pleasant) to access win32 API's.

It's ever so slightly faster than your suggestion @Venryx. Performance metrics taken from my own testing (excerpt from README):

Using this repo. The numbers below were taken over 1000 runs, each at 2560x1440*, outputing bmp.

Library Save to buffer Save to file
windows-ss 52ms 51ms
screenshot-desktop 152ms 141ms
desktop-screenshot n/a 63ms**

* Except for desktop-screenshot, it ran at 1706x960 as it's DPI unaware.

** Times are relative to lower resolution of 1706x960. If interpolated back to 1440p according to a DPI of 1.5, 63 * (1.5 ^ 2) = 141ms

I initially wanted to contribute it to this package, but edge-js only supplies binaries for even-numbered Node versions, requiring building of our own otherwise. :/

sxxov avatar Sep 05 '21 13:09 sxxov

Very nice library!

For most users, I would have to recommend yours -- both because of the better performance, and because it doesn't have a dependency on ffi-napi. (ffi-napi is nice, but it sometimes has build errors when upgrading to newer NodeJS versions, so it can be a pain for people not familiar with the process)

I was looking for a fast screenshotting library a while back, but couldn't find one. If I had seen yours, I probably wouldn't have even created the library above. 😜

That said, it's probably good I went ahead with it, as now there are two options available for people to choose from.

Venryx avatar Sep 05 '21 13:09 Venryx