How to run PlayCanvas headless in the modern day

Hey so I’ve seen a bunch of old forum posts about running playcanvas engine headless, and using old tools like playcanvas-mock or headless-gl, but nothing seems to be up to date from what I’ve seen. I’m trying to render and screenshot a single frame.

Currently I’m using puppeteer but it’s relatively slow. I want to avoid running the browser at all if possible, and run the project directly through node or some other runtime engine. I have a framebuffer-screenshot system working currently.

TL;DR
I want to render and store a screenshot of a PlayCanvas scene as fast as possible. Been stuck for some time so direction is much appreciated.

Thanks in advance :slight_smile:

The issue is that you would need to have something that can handle a WebGL canvas and usually, the easiest is to have headless browser on hardware that can handle 3D rendering natively instead of using the Swift software renderer on Chrome.

There’s also things like GitHub - stackgl/headless-gl: 🎃 Windowless WebGL for node.js that I’ve not used before but looks like it could be an alternative to using a headless browser.

Worth noting that the engine examples browser has a build target to create screenshots for thumbnails. https://github.com/playcanvas/engine/blob/main/examples/package.json#L12

1 Like

Cheers, always appreciate your responses yaustar

Unfortunately I think headless-gl is struggling with age as it only supports WebGL 1 plans for webgl 2 support? · Issue #109 · stackgl/headless-gl · GitHub and I believe PlayCanvas is deprecating WebGL 1 in the near future(?). In any case I got a lot of ‘function not implemented’ errors when trying to work with it. Not sure if anyone else has had better success

And from digging into the build target engine/examples/scripts/build-thumbnails.mjs at main · playcanvas/engine · GitHub “This file spawns a pool of puppeteer instances to take screenshots of each example for thumbnail.” so they’re still using puppeteer for doing it. Makes sense for thumbnails that only run on build, but we need it running fast and often.

For context, we’re trying to actively render and save screenshots of user generated characters using a cheap VPS. Works great and takes about 10 seconds per character with puppeteer. But we need to cut that down to <1 second to scale it for our purposes

At some point in the future you might want to look at headless WebGPU as well, that will likely be a lot better supported than WebGL2.

1 Like

Have you broken down which part of the process takes the time?

Eg browser startup, PlayCanvas app startup, render frame etc?

If it’s known what is taking the time, perhaps there are other ways to bring down that time

Eg, could you have the browser and app already loaded and all it has to do is load the custom character asset, render and deliver the file. That bypasses the initial browser spin up time and app load

2 Likes

Huh. You’re absolutely right, we could just run the app once and then communicate with it to render and save new characters as needed…

Bulk of the work is spinning up the environment itself. Rendering characters takes about a second but can be optimized.

Thank you for giving me a new perspective on a solution, I was too hyperfocused in mine!!

Cheers :slight_smile:

1 Like

You may need to cycle the app/browser every now and then to potentially clear memory or whatever but see how that goes for you :slight_smile:

You could also customise the app a bit so you can stop the update and render loop when it’s not in use so you aren’t spinning cycles/using the CPU unnecessarily

1 Like

Yep, so that ended up working fantastically. I do an npm run serve for my actual project, and alongside that host an esm module running express on localhost that manages a puppeteer instance.

Then I just do little post requests to send commands and auto close/open the browser every X screenshots just in case of leaks. Runs in <1s on the cheapest VPS instance available.

Thanks again! And happy holidays :slight_smile:

3 Likes

FYI, and for future readers, there are a few IaaS platforms that offer this. Notably Cloudflare have a scalable solution using browser instrumentation, similar to Puppeteer Browser Rendering · Browser Rendering docs

1 Like

I know you’re interested in rendering, but I did just write this new user manual page which you might find interesting:

As @mvaligursky suggests, headless WebGPU is probably the future for rendering in Node.js, but as of today, there isn’t yet an official/popular NPM package for this. Although something might grow from this one day:

https://dawn.googlesource.com/dawn/+/refs/heads/main/src/dawn/node/

1 Like