admin管理员组

文章数量:1410705

I'm facing a seriously weird issue with puppeteer, running on Chrome.

I have an array of click actions I want to execute on a webpage, which has a pdf.js based slideshow. Each action consists of information on whether you are navigating to the next or previous slide, and what is the delay of said action in milliseconds. I'm also recording the whole thing.

The problem is that for some reason the first action is always immediately executed regardless of delay. Actions after the first behave as expected.

Things I have tried to no success:

  • Awaiting a timeout between actions.
  • Trying to click with vanilla JS using page.evaluate and waiting inside.
  • Using the built-in delay arg of puppeteer click() function and awaiting the actions
  • Firing random click event before the actual events
  • Updating puppeteer to its latest version
  • Putting random extra actions at the beginning of the actions array
  • Putting a hardcoded delay value into the click

Now I'm wondering that could this be a bug with puppeteer or chromium itself?

Below the current code

export const makeSlideshowVideo = async (
  output_file: string,
  actions: slide_change[],
  url: string,
  webcamLength: number
) => {
  try {
    const executablePath = await chromium.executablePath(
      ".0.0-pack.tar"
    );

    const browser = await puppeteer2.launch({
      executablePath,
      args: [
        `--window-size=${VIDEO_WIDTH},${VIDEO_HEIGHT}`,
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu", // Disable GPU hardware acceleration
        "--disable-dev-shm-usage", // Use /tmp instead of /dev/shm
        "--no-zygote", // Disable zygote process for sandboxing
        // We have to disable security features, so that the browser can load pdf.js from CDN
        // TODO: this is not a safe solution, but might be the fastest fix for now.
        "--disable-web-security",
        "--allow-running-insecure-content",
      ],
      defaultViewport: { width: VIDEO_WIDTH, height: VIDEO_HEIGHT },
    });

    const page = await browser.newPage();

    await page.goto(url);

    // Wait for the slideshow to load
    await sleep(2000);

    const prevBtn = await page.$("#prev");
    const nextBtn = await page.$("#next");

    if (!prevBtn || !nextBtn) {
      throw new Error("No buttons found on the page");
    }

    // Set up the screen recorder
    const recorder = new PuppeteerScreenRecorder(page, recordConfig);

    await recorder.start(output_file);

    let prev = actions[0];
    await sleep(prev.elapsed_millisec);

    for (const next of actions) {
      const delay = next.elapsed_millisec - prev.elapsed_millisec;

      if (next.change_event === change_event.NEXT) {
        await nextBtn.click({ delay: delay });
      } else {
        await prevBtn.click({ delay: delay });
      }

      prev = next;
    }

    await sleep(webcamLength - (prev?.elapsed_millisec ?? 0));

    await recorder.stop();

    return output_file;
  } catch (error) {
    console.error((error as Error).message);
  }
};

Thank for the help!

EDIT

Another non-working version of the code, without sleeping:

export const makeSlideshowVideo = async (
  output_file: string,
  actions: slide_change[],
  url: string,
  webcamLength: number
) => {
  try {
    const executablePath = await chromium.executablePath(
      ".0.0-pack.tar"
    );

    const browser = await puppeteer2.launch({
      executablePath,
      args: [
        `--window-size=${VIDEO_WIDTH},${VIDEO_HEIGHT}`,
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu", // Disable GPU hardware acceleration
        "--disable-dev-shm-usage", // Use /tmp instead of /dev/shm
        "--no-zygote", // Disable zygote process for sandboxing
        // We have to disable security features, so that the browser can load pdf.js from CDN
        // TODO: this is not a safe solution, but might be the fastest fix for now.
        "--disable-web-security",
        "--allow-running-insecure-content",
      ],
      defaultViewport: { width: VIDEO_WIDTH, height: VIDEO_HEIGHT },
    });

    const page = await browser.newPage();

    await page.goto(url);

    // Wait for the slideshow to load
    await sleep(2000);

    const prevBtn = await page.$("#prev");
    const nextBtn = await page.$("#next");

    if (!prevBtn || !nextBtn) {
      throw new Error("No buttons found on the page");
    }

    // Set up the screen recorder
    const recorder = new PuppeteerScreenRecorder(page, recordConfig);

    await recorder.start(output_file);

    let prev = null;

    for (const next of actions) {
      const delay = next.elapsed_millisec - (prev?.elapsed_millisec ?? 0);

      if (next.change_event === change_event.NEXT) {
        await nextBtn.click({ delay: delay });
      } else {
        await prevBtn.click({ delay: delay });
      }

      prev = next;
    }

    await sleep(webcamLength - (prev?.elapsed_millisec ?? 0));

    await recorder.stop();

    return output_file;
  } catch (error) {
    console.error((error as Error).message);
  }
};

I'm facing a seriously weird issue with puppeteer, running on Chrome.

I have an array of click actions I want to execute on a webpage, which has a pdf.js based slideshow. Each action consists of information on whether you are navigating to the next or previous slide, and what is the delay of said action in milliseconds. I'm also recording the whole thing.

The problem is that for some reason the first action is always immediately executed regardless of delay. Actions after the first behave as expected.

Things I have tried to no success:

  • Awaiting a timeout between actions.
  • Trying to click with vanilla JS using page.evaluate and waiting inside.
  • Using the built-in delay arg of puppeteer click() function and awaiting the actions
  • Firing random click event before the actual events
  • Updating puppeteer to its latest version
  • Putting random extra actions at the beginning of the actions array
  • Putting a hardcoded delay value into the click

Now I'm wondering that could this be a bug with puppeteer or chromium itself?

Below the current code

export const makeSlideshowVideo = async (
  output_file: string,
  actions: slide_change[],
  url: string,
  webcamLength: number
) => {
  try {
    const executablePath = await chromium.executablePath(
      "https://my-cdn.s3.eu-north-1.amazonaws/chromium-v132.0.0-pack.tar"
    );

    const browser = await puppeteer2.launch({
      executablePath,
      args: [
        `--window-size=${VIDEO_WIDTH},${VIDEO_HEIGHT}`,
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu", // Disable GPU hardware acceleration
        "--disable-dev-shm-usage", // Use /tmp instead of /dev/shm
        "--no-zygote", // Disable zygote process for sandboxing
        // We have to disable security features, so that the browser can load pdf.js from CDN
        // TODO: this is not a safe solution, but might be the fastest fix for now.
        "--disable-web-security",
        "--allow-running-insecure-content",
      ],
      defaultViewport: { width: VIDEO_WIDTH, height: VIDEO_HEIGHT },
    });

    const page = await browser.newPage();

    await page.goto(url);

    // Wait for the slideshow to load
    await sleep(2000);

    const prevBtn = await page.$("#prev");
    const nextBtn = await page.$("#next");

    if (!prevBtn || !nextBtn) {
      throw new Error("No buttons found on the page");
    }

    // Set up the screen recorder
    const recorder = new PuppeteerScreenRecorder(page, recordConfig);

    await recorder.start(output_file);

    let prev = actions[0];
    await sleep(prev.elapsed_millisec);

    for (const next of actions) {
      const delay = next.elapsed_millisec - prev.elapsed_millisec;

      if (next.change_event === change_event.NEXT) {
        await nextBtn.click({ delay: delay });
      } else {
        await prevBtn.click({ delay: delay });
      }

      prev = next;
    }

    await sleep(webcamLength - (prev?.elapsed_millisec ?? 0));

    await recorder.stop();

    return output_file;
  } catch (error) {
    console.error((error as Error).message);
  }
};

Thank for the help!

EDIT

Another non-working version of the code, without sleeping:

export const makeSlideshowVideo = async (
  output_file: string,
  actions: slide_change[],
  url: string,
  webcamLength: number
) => {
  try {
    const executablePath = await chromium.executablePath(
      "https://my-cdn.s3.eu-north-1.amazonaws/chromium-v132.0.0-pack.tar"
    );

    const browser = await puppeteer2.launch({
      executablePath,
      args: [
        `--window-size=${VIDEO_WIDTH},${VIDEO_HEIGHT}`,
        "--no-sandbox",
        "--disable-setuid-sandbox",
        "--disable-gpu", // Disable GPU hardware acceleration
        "--disable-dev-shm-usage", // Use /tmp instead of /dev/shm
        "--no-zygote", // Disable zygote process for sandboxing
        // We have to disable security features, so that the browser can load pdf.js from CDN
        // TODO: this is not a safe solution, but might be the fastest fix for now.
        "--disable-web-security",
        "--allow-running-insecure-content",
      ],
      defaultViewport: { width: VIDEO_WIDTH, height: VIDEO_HEIGHT },
    });

    const page = await browser.newPage();

    await page.goto(url);

    // Wait for the slideshow to load
    await sleep(2000);

    const prevBtn = await page.$("#prev");
    const nextBtn = await page.$("#next");

    if (!prevBtn || !nextBtn) {
      throw new Error("No buttons found on the page");
    }

    // Set up the screen recorder
    const recorder = new PuppeteerScreenRecorder(page, recordConfig);

    await recorder.start(output_file);

    let prev = null;

    for (const next of actions) {
      const delay = next.elapsed_millisec - (prev?.elapsed_millisec ?? 0);

      if (next.change_event === change_event.NEXT) {
        await nextBtn.click({ delay: delay });
      } else {
        await prevBtn.click({ delay: delay });
      }

      prev = next;
    }

    await sleep(webcamLength - (prev?.elapsed_millisec ?? 0));

    await recorder.stop();

    return output_file;
  } catch (error) {
    console.error((error as Error).message);
  }
};
Share Improve this question edited Mar 4 at 15:46 Juhana Kuparinen asked Mar 4 at 14:26 Juhana KuparinenJuhana Kuparinen 414 bronze badges 9
  • next.elapsed_millisec - prev.elapsed_millisec this is zero for the first iteration. – James Commented Mar 4 at 14:34
  • Yes, but we are sleeping before that. Also, the delay won't work for the first action even if we don't sleep and the delay is larger than 0 (we wait for only next.elapsed_millisec. – Juhana Kuparinen Commented Mar 4 at 14:45
  • If actions[0].elapsed_millisec is zero you could also get the problem you describe. – James Commented Mar 4 at 14:52
  • I've inspected it, and it is not zero. Also, putting the hardcoded value into the delays should have solved the issue in that case :/ – Juhana Kuparinen Commented Mar 4 at 14:57
  • 1 When you say you tried "Awaiting a timeout between actions", do you mean using sleep function? If yes, what is the function body? – Gabriele Coletta Commented Mar 4 at 15:16
 |  Show 4 more comments

1 Answer 1

Reset to default 0

The issue is solved.

It seems like this is some kind of a bug with puppeteer-screen-recorder version 2. Simply update to version 3 to fix the issue!

So in package.json

{
  ...
  "dependencies": {
    ...
    "puppeteer-screen-recorder": "^2.1.2" -> "^3.0.6",
  },
  ...
}

fixed it for me.

本文标签: