Запись звука и захват экрана

В этом руководстве описаны различные подходы к записи аудио и видео с вкладки, окна или экрана с использованием таких API, как browser.tabCapture или getDisplayMedia() .

Запись экрана

Для записи экрана вызовите метод getDisplayMedia() , который откроет диалоговое окно, показанное ниже. Это позволит пользователю выбрать вкладку, окно или экран, которым он хочет поделиться, и обеспечит четкое отображение процесса записи.

Диалог демонстрации экрана для example.com
Диалоговое окно демонстрации экрана для example.com.

В следующем примере запрашивается доступ на запись как аудио, так и видео.

const stream = await navigator.mediaDevices.getDisplayMedia({ audio: true, video: true });

Если запись вызывается внутри скрипта контента, она автоматически завершится, когда пользователь перейдет на новую страницу. Для записи в фоновом режиме и при переходе между страницами используйте документ, находящийся вне экрана , с причиной DISPLAY_MEDIA .

Захват вкладок на основе жестов пользователя

Вызов функции getDisplayMedia() приводит к отображению в браузере диалогового окна с вопросом о том, чем пользователь хочет поделиться. Однако в некоторых случаях пользователь только что нажал на кнопку действия для запуска вашего расширения для определенной вкладки, и вам нужно немедленно начать захват вкладки без этого запроса.

Запись аудио и видео в фоновом режиме.

Начиная с Chrome 116, вы можете вызвать API browser.tabCapture в сервис-воркере, чтобы получить идентификатор потока вслед за жестом пользователя. Затем этот идентификатор можно передать документу, находящемуся за пределами экрана, для начала записи.

В вашей сфере услуг:

browser.action.onClicked.addListener(async (tab) => {
  const existingContexts = await browser.runtime.getContexts({});

  const offscreenDocument = existingContexts.find(
    (c) => c.contextType === 'OFFSCREEN_DOCUMENT'
  );

  // If an offscreen document is not already open, create one.
  if (!offscreenDocument) {
    // Create an offscreen document.
    await browser.offscreen.createDocument({
      url: 'offscreen.html',
      reasons: ['USER_MEDIA'],
      justification: 'Recording from browser.tabCapture API',
    });
  }

  // Get a MediaStream for the active tab.
  const streamId = await browser.tabCapture.getMediaStreamId({
    targetTabId: tab.id
  });

  // Send the stream ID to the offscreen document to start recording.
  browser.runtime.sendMessage({
    type: 'start-recording',
    target: 'offscreen',
    data: streamId
  });
});

Затем в вашем документе, находящемся вне экрана:

browser.runtime.onMessage.addListener(async (message) => {
  if (message.target !== 'offscreen') return;
  
  if (message.type === 'start-recording') {
    const media = await navigator.mediaDevices.getUserMedia({
      audio: {
        mandatory: {
          chromeMediaSource: "tab",
          chromeMediaSourceId: message.data,
        },
      },
      video: {
        mandatory: {
          chromeMediaSource: "tab",
          chromeMediaSourceId: message.data,
        },
      },
    });

    // Continue to play the captured audio to the user.
    const output = new AudioContext();
    const source = output.createMediaStreamSource(media);
    source.connect(output.destination);

    // TODO: Do something to record the MediaStream.
  }
});

Полный пример можно посмотреть в образце Tab Capture - Recorder .

Запись аудио и видео в новой вкладке

До версии Chrome 116 было невозможно использовать API browser.tabCapture в сервис-воркере или получать идентификатор потока, созданный этим API, в документе, находящемся вне экрана. Оба эти условия необходимы для описанного выше подхода.

Вместо этого вы можете открыть страницу расширения в новой вкладке или окне и напрямую получить поток. Установите свойство targetTabId чтобы получить доступ к нужной вкладке.

Для начала откройте страницу расширения (возможно, во всплывающем окне или сервис-воркере):

browser.windows.create({ url: browser.runtime.getURL("recorder.html") });

Затем на странице вашего расширения:

browser.tabCapture.getMediaStreamId({ targetTabId: tabId }, async (id) => {
  const media = await navigator.mediaDevices.getUserMedia({
    audio: {
      mandatory: {
        chromeMediaSource: "tab",
        chromeMediaSourceId: id,
      },
    },
    video: {
      mandatory: {
        chromeMediaSource: "tab",
        chromeMediaSourceId: id,
      },
    },
  });

  // Continue to play the captured audio to the user.
  const output = new AudioContext();
  const source = output.createMediaStreamSource(media);
  source.connect(output.destination);
});

В качестве альтернативы можно рассмотреть метод записи экрана , который позволяет записывать в фоновом режиме, используя документ, находящийся вне поля зрения, но при этом отображает пользователю диалоговое окно для выбора вкладки, окна или экрана для записи.

Запись звука во всплывающем окне

Если вам нужно только записать звук, вы можете получить поток непосредственно во всплывающем окне расширения, используя browser.tabCapture.capture . Когда всплывающее окно закроется, запись будет остановлена.

browser.tabCapture.capture({ audio: true }, (stream) => {
  // Continue to play the captured audio to the user.
  const output = new AudioContext();
  const source = output.createMediaStreamSource(stream);
  source.connect(output.destination);

  // TODO: Do something with the stream (e.g record it)
});

Если вам необходимо, чтобы запись сохранялась при переходе между страницами навигации, рассмотрите подход, описанный в предыдущем разделе .

Другие соображения

Для получения более подробной информации о том, как записывать поток, см. API MediaRecorder .