Headless puppeteer 屏幕截图未呈现 WebGL canvas

Headless puppeteer screenshot not rendering WebGL canvas

我正在尝试在无头模式下使用 puppeteer 截取 website (in which I control) 的屏幕截图。

问题是,我的网站上有一个 WebGL canvas 无法在无头模式屏幕截图中呈现(但在有头模式下工作)。

我在无头模式下得到的只是一个黑色的 PNG。

我试过将 WebGL 上下文参数更改为多个组合,但没有任何效果。

我使用的是 puppeteer 5.5.0 版和 chromium 88.0.4298.0 版

这是我的 puppeteer 爬虫代码:

const puppeteer = require("puppeteer");

const url = "https://phcs93.github.io/genesis/";

async function crawl () {
    const browser = await puppeteer.launch({
        headless: true,
        args: [
            '--no-sandbox', 
            '--disable-setuid-sandbox', 
            '--mute-audio'
        ]
    });
    const page = await browser.newPage();
    await page.goto(url, {
        "waitUntil": "networkidle0",
        "timeout": 0
    });
    await page.screenshot({ path: "screenshot.png" });
    await browser.close();
}

(async () => await crawl())();

这些是我在网站的 WebGL 上下文中使用的当前参数:

const gl = canvas.getContext("webgl2", {
    preserveDrawingBuffer: true,
    alpha: false,
    antialias: true,
    premultipliedAlpha: true
});

经过大量调试,发现问题所在:

在我的一个着色器 (gradient.glsl) 中,我有这个:

uniform float[256] breakpoints;
uniform vec4[256] colors;

改成这样,问题解决:

uniform float[122] breakpoints;
uniform vec4[122] colors;

两个数组的任何大于 122 的值都不起作用。

现在更奇怪的部分来了,这个有效:

uniform float[244] breakpoints; // 245 or more wont work
// uniform vec4[122] colors;

这行不通:

// uniform float[122] breakpoints;
uniform vec4[244] colors; // only 243 or less

我还没有进一步测试,看起来像无头模式的某种内存限制?

提示: 可以使用 puppeteer 从页面捕获所有控制台消息,只需在 page.goto:

之前添加
page.on('console', message => console.log(`${message.type().substr(0, 3).toUpperCase()} ${message.text()}`));
page.on('pageerror', ({ message }) => console.log(message));
page.on('response', response => console.log(`${response.status()} ${response.url()}`));
page.on('requestfailed', request => console.log(`${request.failure().errorText} ${request.url()}`));

这样做可以节省我很多调试时间。