puppeteer: Can not render a WebGL image for PDF -- get a black box instead

Summary:

I am trying to get a PDF of a page that has a panoramic image on it using Puppeteer. The panoramic image is rendered using WebGL, which I suspect to be the issue. All I get is a black box instead of the image (see the bottom of this post for screen image). But, I can use Puppeteer to get a screenshot of that same page and the panorama looks great. I am not sure why it won’t render when I attempt getting a PDF, but works for screenshot.

Steps to reproduce

Tell us about your environment:

  • Puppeteer version: puppeteer@0.10.2
  • Platform / OS version: Linux c1301da96bb5 4.9.49-moby running in a Docker container
  • URLs (if applicable):
  • Node.js version: 8.8.1 (NOTE: the code below was originally developed in 6.1, but we now run 8.8.1)

What steps will reproduce the problem?

Please include code that reproduces the issue.

  1. Using this code:
var page, browser;
return Puppeteer.launch({args: options.chromeArgs})
    .then(res => {
        if (!res) {
            return reject(new Error("No browser to open"));
        }
        browser = res;
        return browser.newPage();
    })
    .then(res => {
        if (!res) {
            throw new Error("No browswer available");
         }
        page = res;
        return page.setViewport({
            height: 720,
            width: 1280,
            isLandscape: true,
        ));
    })
    .then(() => {
        return page.goto(url,{"waitUntil":"networkidle0"});
    })
    .then(() => {
        return page.pdf(options);
    })
    .then(buffer => {
       if (browser) {
           browser.close();
       }
       return resolve(buffer);
    })
    .catch(err => {
        if (browser) {
            browser.close();
        }
        return reject(err);
    });
  1. I have tried these options:
            "pageTimeout": 120000,
            "chromeArgs": ["--disable-gpu","--disable-setuid-sandbox","--no-sandbox"],
            "headless": true,
            "printBackground": true,
            "displayHeaderFooter": true,
            "landscape": true,
            "margin": {
                "top": 0,
                "bottom": 0,
                "left": 0,
                "right": 0
            }
        }
  1. I have also tried adding these the the chromeArgs: --use-gl=swiftshader --use-gl=osmesa --use-gl=swiftshader-webgl

What is the expected result? I would expect the PDF to look like the screenshot – like this 004

Here is the screenshot from Puppeteer (NOTE: the html page is formatted slightly differently for PDF rendering, but the panoramic image is the same) 0002

What happens instead? The PDF has a black box where the panoramic image should be. 003

About this issue

  • Original URL
  • State: closed
  • Created 6 years ago
  • Reactions: 4
  • Comments: 35 (5 by maintainers)

Most upvoted comments

For some reason the mapbox issue affects pdf but not screenshots, so my workaround was to replace canvases with screenshots:

let canvases = await page.$$('canvas')
for(let canvas of canvases){
    let str = await canvas.screenshot({ encoding: "base64" })
    let dataUrl = 'data:image/png;base64,' + str
    await canvas.evaluate((canvas, dataUrl) => {
      const newDiv = document.createElement('div')
      newDiv.innerHTML = '<img src="' + dataUrl + '">'
      canvas.parentNode.replaceChild(newDiv, canvas)
    }, dataUrl)
}

@ianformanek Make sure you’re using preserveDrawingBuffer: true.

Any update on this thread: The issue is still coming for “puppeteer”: “^2.0.0”. With headless mode, on taking the screenshot of a canvas element it’s getting the blank output, but on running the same code with headlfull mode it’s working just fine.

Yeah, this is it! Creating the mapbox-gl instances like this:

      map = new mapboxgl.Map({
        container: '...',
        ...,
        preserveDrawingBuffer: true
      });

fixes the issue when the map would be empty when using puppeteer to render pdf (probably limited to rendering on server without a GPU).

It is still interesting that pdf and image behave differently in this regard, but probably has to do with timing. See also https://github.com/mapbox/mapbox-gl-js/issues/6448

Thanks!

I’m seeing this issue when I try to render a PDF containing a mapbox-gl-js map on the latest release of Puppeteer (5.3.1) on Ubuntu server 18.04 LTS.

I’ve tried using the bundled Chromium version and latest releases of Chrome and Chrome Beta - all give the same result.

I’ve tried setting the preserveDrawingBuffer: true option on the Mapbox map.

If I set dumpio: true when launching Puppeteer, I do see this error message:

[1019/145021.772786:ERROR:command_buffer_proxy_impl.cc(122)] ContextResult::kTransientFailure: Failed to send GpuChannelMsg_CreateCommandBuffer.

Screenshot 2020-10-19 at 15 48 51

I had better luck with this solution: https://github.com/GoogleChrome/puppeteer/issues/1260#issuecomment-348878456, specifically for MapboxGL.