Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Bug]: Crash when Using getDisplayMedia API #13478

Open
ViniciusFXavier opened this issue Jan 9, 2025 · 2 comments
Open

[Bug]: Crash when Using getDisplayMedia API #13478

ViniciusFXavier opened this issue Jan 9, 2025 · 2 comments

Comments

@ViniciusFXavier
Copy link

ViniciusFXavier commented Jan 9, 2025

Description

The issue occurs when calling await navigator.mediaDevices.getDisplayMedia(displayMediaOptions) within a browser instance controlled by Puppeteer, regardless of the displayMediaOptions provided. If a media stream is initiated, the Puppeteer process crashes on try to close the page.

Notably, this issue does not occur when running the same code directly in Chromium or any other browser outside of Puppeteer, where the functionality works as expected. However, when executed via Puppeteer—either within page.evaluate() or directly in the DevTools console—the browser crashes.

Minimal, reproducible example

Automatic Reproduction
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: [
      '--auto-accept-this-tab-capture',
      '--autoplay-policy=no-user-gesture-required',
    ],
    headless: false,
  });

  let page = await browser.newPage();

  page.once('load', async () => {
    const result = await page.evaluate(async () => {
      const displayMediaOptions = {
        video: { displaySurface: "window" },
        audio: false,
        preferCurrentTab: true,
      };

      await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); // Causes crash
      return 1 + 1;
    });

    console.log('Result:', result);

    await new Promise(resolve => setTimeout(resolve, 5000)); // 5-second delay
    await page.close(); // Crash occurs here if tab is capturing media

    await new Promise(resolve => setTimeout(resolve, 5000)); // 5-second delay
    page = await browser.newPage(); // Error occurs here
  });

  await page.goto('https://pptr.dev/');
})();
Manual Reproduction
const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: [
      '--auto-accept-this-tab-capture',
      '--autoplay-policy=no-user-gesture-required',
    ],
    headless: false,
  });

  const page = await browser.newPage();
  await page.goto('https://pptr.dev/');

  // Go to the DevTools console and execute the following script:
  /*
   * const displayMediaOptions = {
   *   video: { displaySurface: "window" },
   *   audio: false,
   *   preferCurrentTab: true,
   * };
   * await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
   * // Then try to close the page.
   */
})();

Justification for Arguments

The arguments provided in the Puppeteer launch configuration are not the cause of the issue, as the problem persists even without them. Here's a breakdown of their purpose:

  1. --auto-accept-this-tab-capture:

    • This flag enables automatic tab capture without requiring additional scripts or manual permissions from the user. It simplifies the workflow for scenarios involving screen sharing or tab streaming, ensuring smooth initialization without unnecessary prompts or setup.
    • Removing this argument does not resolve the crash, confirming it is not contributing to the problem.
  2. --autoplay-policy=no-user-gesture-required:

    • This flag allows media playback (e.g., starting a video on YouTube) without user interaction. It is essential for automated testing or workflows where user gestures cannot be simulated in real-time.
    • The issue occurs even if this argument is omitted, further ruling out its involvement in the crash.

These arguments are practical enhancements for automation and do not interfere with the underlying browser operations.

Background

I am using the browser to perform server-side rendering of operations executed within the browser environment. This setup allows me to use navigator.mediaDevices.getDisplayMedia to capture and stream data via P2P connections to my clients. In addition to P2P, I also use WebSocket connections to transmit the data efficiently.

The issue arises when a client disconnects, and I close the tab to conserve resources, as it is no longer needed. At this point, the crash occurs.

Using navigator.mediaDevices.getDisplayMedia to capture and send streaming data is currently one of the most efficient methods available for minimizing both bandwidth usage and processing overhead, making it essential to my workflow.

Expectation

  • Closing a page with page.close() or manually while streaming media should not affect the browser connection.
  • A new page should be openable with browser.newPage() without encountering errors.

Reality

The process crashes, resulting in the following error:

Error: Protocol error: Connection closed.
    at Connection._rawSend (/home/vfx/projects/test-bug/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Connection.js:91:35)
    at Connection.send (/home/vfx/projects/test-bug/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Connection.js:84:21)
    at CdpBrowser._createPageInContext (/home/vfx/projects/test-bug/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js:186:53)
    at CdpBrowserContext.newPage (/home/vfx/projects/test-bug/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/BrowserContext.js:123:40)
    at async CdpBrowser.newPage (/home/vfx/projects/test-bug/node_modules/puppeteer-core/lib/cjs/puppeteer/cdp/Browser.js:183:16)
    at async /home/vfx/projects/test-bug/sandbox.js:32:12

Puppeteer configuration file (if used)

No response

Puppeteer version

23.11.1

Node version

22.3.0

Package manager

npm

Package manager version

10.8.1

Operating system

Linux

@OrKoN
Copy link
Collaborator

OrKoN commented Jan 9, 2025

Simplified script:

const puppeteer = require('puppeteer');

(async () => {
  const browser = await puppeteer.launch({
    args: [
      '--auto-accept-this-tab-capture',
      '--autoplay-policy=no-user-gesture-required',
    ],
    dumpio: true,
    headless: false,
  });

  const page = await browser.newPage();

  await page.goto('https://pptr.dev/');

  const result = await page.evaluate(async () => {
    const displayMediaOptions = {
      video: { displaySurface: "window" },
      audio: false,
      preferCurrentTab: true,
    };

    await navigator.mediaDevices.getDisplayMedia(displayMediaOptions); // Causes crash
    return 1 + 1;
  });

  console.log('Result:', result);

  await page.close(); // Crash occurs here if tab is capturing media
})();

this is a crash in Chrome as indicated by the browser logs:

[1483458:1483458:0109/071658.095440:ERROR:observer_list.h(295)] Check failed: observers_.empty(). 
For observer stack traces, build with `dcheck_always_on=tru

@OrKoN
Copy link
Collaborator

OrKoN commented Jan 9, 2025

Looks like it has been filed upstream https://crbug.com/327489285

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

2 participants