Spec-Zone.ru › Web APIs

Использование API захвата экрана

Ограниченная доступность

Эта функция не относится к Baseline, так как она не работает в некоторых из самых популярных браузеров.

  • Подробнее
  • Полная совместимость
  • Отправить отзыв

В этой статье мы рассмотрим, как использовать API захвата экрана и его метод getDisplayMedia() для захвата части или всего экрана для потоковой передачи, записи или совместного использования во время сессии конференции WebRTC.

Примечание: Возможно, полезно отметить, что недавние версии платёжки адаптера WebRTC включают реализации getDisplayMedia() для включения совместного использования экрана в браузерах, которые поддерживают его, но не реализуют текущий стандартный API. Это работает хотя бы в Chrome, Edge и Firefox.

Захват содержимого экрана

Захват содержимого экрана в виде живого MediaStream инициируется вызовом navigator.mediaDevices.getDisplayMedia(), который возвращает обещание, которое выполняется потоком, содержащим живое содержимое экрана. Объект displayMediaOptions, на который ссылаются в примерах ниже, может выглядеть примерно так:

const displayMediaOptions = {
  video: {
    displaySurface: "browser",
  },
  audio: {
    suppressLocalAudioPlayback: false,
  },
  preferCurrentTab: false,
  selfBrowserSurface: "exclude",
  systemAudio: "include",
  surfaceSwitching: "include",
  monitorTypeSurfaces: "include",
};

Запуск захвата экрана: стиль async/await

async function startCapture(displayMediaOptions) {
  let captureStream = null;

  try {
    captureStream =
      await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
  } catch (err) {
    console.error(`Error: ${err}`);
  }
  return captureStream;
}

Этот код можно написать как с помощью асинхронной функции и оператора await, как показано выше, так и с использованием Promise напрямую, как показано ниже.

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

function startCapture(displayMediaOptions) {
  return navigator.mediaDevices
    .getDisplayMedia(displayMediaOptions)
    .catch((err) => {
      console.error(err);
      return null;
    });
}

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

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

Пример окна, позволяющего пользователю выбрать поверхность отображения для захвата

Screenshot of Chrome's window for picking a source surface

Затем вы можете использовать захваченный поток, captureStream, для всего, что принимает поток в качестве входных данных. Примеры ниже показывают несколько способов использования потока.

Видимые и логические поверхности отображения

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

Существует два типа поверхностей отображения. Видимая поверхность отображения — это поверхность, которая полностью видна на экране, например, самое переднее окно или вкладка или весь экран.

Логическая поверхность отображения — это поверхность, которая частично или полностью скрыта, либо из-за перекрытия другим объектом, либо из-за полного скрытия или вывода за экран. Способ обработки этих поверхностей API захвата экрана различается. Как правило, браузер предоставляет изображение, которое скрывает скрытую часть логической поверхности отображения каким-либо образом, например, с помощью размытия или замены цветом или узором. Это делается по соображениям безопасности, так как содержимое, которое пользователь не видит, может содержать данные, которые он не хочет делиться.

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

Параметры и ограничения

Объект параметров, передаваемый в getDisplayMedia(), используется для установки параметров результирующего потока.

Объекты video и audio , передаваемые в объект параметров, также могут содержать дополнительные ограничения, относящиеся к этим медиапотокам. Подробности о дополнительных ограничениях для настройки потока захвата экрана, которые добавляются к MediaTrackConstraints, MediaTrackSupportedConstraints и MediaTrackSettings, см. в разделе «Свойства треков совместно используемого экрана».

Ни одно из ограничений не применяется каким-либо образом до тех пор, пока не будет выбран контент для захвата. Ограничения изменяют то, что вы видите в результирующем потоке. Например, если вы укажете ограничение width для видео, оно применяется путём масштабирования видео после того, как пользователь выберет область для совместного использования. Оно не устанавливает ограничение на размер исходника самого себя.

Примечание: Ограничения никогда не приводят к изменению списка источников, доступных для захвата API совместного использования экрана. Это гарантирует, что веб-приложения не могут заставить пользователя поделиться определённым содержимым, ограничивая список источников до тех пор, пока не останется только один элемент.

В то время как происходит захват отображения, машина, которая разделяет содержимое экрана, отображает какой-либо индикатор, чтобы пользователь знал, что совместное использование происходит.

Примечание: По соображениям конфиденциальности и безопасности источники совместного использования экрана не перечисляются с помощью enumerateDevices(). В связи с этим событие devicechange никогда не отправляется при изменении доступных источников для getDisplayMedia().

Захват общего звука

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

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

Для того, чтобы запросить совместное использование экрана со звуком, параметры, передаваемые в getDisplayMedia() , могут выглядеть следующим образом:

const displayMediaOptions = {
  video: true,
  audio: true,
};

Это позволяет пользователю полностью выбрать то, что он хочет, в пределах возможностей пользовательского агента. Это можно дополнительно уточнить, указав дополнительные параметры и ограничения внутри объектов audio и video:

const displayMediaOptions = {
  video: {
    displaySurface: "window",
  },
  audio: {
    echoCancellation: true,
    noiseSuppression: true,
    sampleRate: 44100,
    suppressLocalAudioPlayback: true,
  },
  surfaceSwitching: "include",
  selfBrowserSurface: "exclude",
  systemAudio: "exclude",
};

В этом примере захватываемая поверхность отображения — это всё окно. Треку аудио желательно включить подавление шумов и эха, а также идеальную частоту дискретизации 44,1 кГц и подавление локального воспроизведения аудио.

Кроме того, приложение даёт подсказку пользовательскому агенту, что он должен:

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

Захват аудио всегда необязателен, и даже когда веб-контент запрашивает поток с аудио и видео, возвращённый MediaStream всё ещё может содержать только один видеопоток без аудио.

Использование захваченного потока

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

Возможные риски

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

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

Пользовательские агенты, которые серьёзно относятся к конфиденциальности, должны маскировать содержимое, которое фактически не отображается на экране, если не получено разрешение на совместное использование этого содержимого специально.

Разрешение захвата содержимого экрана

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

Примеры

Потоковая передача захвата экрана

В этом примере содержимое области захвата экрана передаётся в элемент <video> на той же странице.

JavaScript

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

Настройка

Сначала задаются некоторые константы, ссылающиеся на элементы страницы, к которым нам потребуется доступ: элемент <video>, в который будет передаваться содержимое захвата экрана, блок для вывода логов и кнопки «Начать» и «Остановить», которые будут включать и выключать захват изображений экрана.

Объект displayMediaOptions содержит параметры, которые передаются в getDisplayMedia(); здесь свойство displaySurface установлено в значение window, что указывает на захват всего окна.

Наконец, устанавливаются обработчики событий для обнаружения нажатий пользователя на кнопки «Начать» и «Остановить».

const videoElem = document.getElementById("video");
const logElem = document.getElementById("log");
const startElem = document.getElementById("start");
const stopElem = document.getElementById("stop");

// Options for getDisplayMedia()

const displayMediaOptions = {
  video: {
    displaySurface: "window",
  },
  audio: false,
};

// Set event listeners for the start and stop buttons
startElem.addEventListener(
  "click",
  (evt) => {
    startCapture();
  },
  false,
);

stopElem.addEventListener(
  "click",
  (evt) => {
    stopCapture();
  },
  false,
);
Вывод логов

В этом примере переопределяются определённые методы console для вывода сообщений в блок <pre> с идентификатором log.

console.log = (msg) => (logElem.textContent = `${logElem.textContent}\n${msg}`);
console.error = (msg) =>
  (logElem.textContent = `${logElem.textContent}\nError: ${msg}`);

Это позволяет нам использовать console.log() и console.error() для записи информации в лог-блок документа.

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

Метод startCapture() ниже запускает захват MediaStream, содержимое которого взято из выбранной пользователем области экрана. startCapture() вызывается при нажатии на кнопку «Начать захват».

async function startCapture() {
  logElem.textContent = "";

  try {
    videoElem.srcObject =
      await navigator.mediaDevices.getDisplayMedia(displayMediaOptions);
    dumpOptionsInfo();
  } catch (err) {
    console.error(err);
  }
}

После очистки содержимого лога для удаления оставшегося текста из предыдущей попытки подключения, startCapture() вызывает getDisplayMedia(), передавая в него объект ограничений, определённый displayMediaOptions. Используя await, следующая строка кода не выполняется до тех пор, пока не разрешится promise, возвращённый getDisplayMedia(). После разрешения промис возвращает MediaStream, который будет транслировать содержимое экрана, окна или другой области, выбранной пользователем.

Поток подключается к элементу <video> путём сохранения возвращённого значения MediaStream в свойство srcObject элемента.

Функция dumpOptionsInfo() — которую мы рассмотрим чуть позже — выводит информацию о потоке в лог-блок для образовательных целей.

Если что-то пойдёт не так, блок catch() выведет сообщение об ошибке в лог-блок.

Остановка захвата экрана

Метод stopCapture() вызывается при нажатии на кнопку «Остановить захват». Он останавливает поток, получая список треков с помощью MediaStream.getTracks(), а затем вызывая метод stop() каждого трека. После этого srcObject устанавливается в значение null для того, чтобы всем заинтересованным было понятно, что соединение с потоком отсутствует.

function stopCapture(evt) {
  let tracks = videoElem.srcObject.getTracks();

  tracks.forEach((track) => track.stop());
  videoElem.srcObject = null;
}
Вывод информации о конфигурации

Для информационных целей метод startCapture() выше вызывает метод dumpOptions(), который выводит текущие настройки треков, а также ограничения, заданные для потока при его создании.

function dumpOptionsInfo() {
  const videoTrack = videoElem.srcObject.getVideoTracks()[0];

  console.log("Track settings:");
  console.log(JSON.stringify(videoTrack.getSettings(), null, 2));
  console.log("Track constraints:");
  console.log(JSON.stringify(videoTrack.getConstraints(), null, 2));
}

Список треков получается путём вызова getVideoTracks() на MediaStream захваченного экрана. Текущие настройки получаются с помощью getSettings(), а установленные ограничения — с помощью getConstraints().

HTML

HTML начинается с вводного абзаца, а затем переходит к сути дела.

<p>
  This example shows you the contents of the selected part of your display.
  Click the Start Capture button to begin.
</p>

<p>
  <button id="start">Start Capture</button>&nbsp;<button id="stop">
    Stop Capture
  </button>
</p>

<video id="video" autoplay></video>
<br />

<strong>Log:</strong>
<br />
<pre id="log"></pre>

Ключевыми частями HTML являются:

  1. Кнопка <button> с надписью «Начать захват», которая при нажатии вызывает функцию startCapture() для запроса доступа к содержимому экрана и начала его захвата.
  2. Вторая кнопка «Остановить захват», которая при нажатии вызывает stopCapture() для прекращения захвата содержимого экрана.
  3. Элемент <video>, в который передаётся содержимое захваченного экрана.
  4. Блок <pre>, в который перехваченный метод console помещает выведенный текст.

CSS

CSS в этом примере полностью косметический. Видео получает границу, и его ширина устанавливается практически на всю доступную горизонтальную область (width: 98%). max-width устанавливается в значение 860px для задания абсолютного верхнего предела размера видео.

#video {
  border: 1px solid #999;
  width: 98%;
  max-width: 860px;
}

#log {
  width: 25rem;
  height: 15rem;
  border: 1px solid black;
  padding: 0.5rem;
  overflow: scroll;
}

Результат

Конечный продукт выглядит так. Если ваш браузер поддерживает API захвата экрана, нажатие на «Начать захват» отобразит интерфейс пользовательского агента для выбора экрана, окна или вкладки для совместного использования.

Безопасность

Для работы при включённой политике разрешений Permissions Policy вам потребуется разрешение display-capture. Это можно сделать, используя заголовок Permissions-Policy HTTP или — если вы используете API захвата экрана во <iframe>, — атрибут allow элемента <iframe>.

Например, эта строка в заголовках HTTP включит API захвата экрана для документа и любых вложенных элементов <iframe>, загружаемых с того же источника:

Permissions-Policy: display-capture=(self)

Если вы выполняете захват экрана в <iframe>, вы можете запросить разрешение только для этой рамки, что, очевидно, более безопасно, чем запрос разрешения в целом:

<iframe src="https://mycode.example.net/etc" allow="display-capture"> </iframe>

Совместимость с браузерами

Рабочий стол Мобильные устройства
Chrome Edge Firefox Opera Safari Chrome Android Firefox для Android Opera Android Safari на IOS Samsung Internet WebView Android
Using_Screen_Capture 72 79
17–79Доступен в качестве члена Navigator вместо MediaDevices.
66
33–66Начиная с Firefox 33, вы можете захватывать данные экрана с помощью getUserMedia() с ограничением video под названием mediaSource. До версии 52 использовался настраиваемый клиентом список разрешённых сайтов.
60 13
НетВ Chrome Android с 72 по 88 этот метод был доступен, но всегда завершался ошибкой NotAllowedError. См. ошибку 40418135.
НетВ Firefox Android с 66 по 79 этот метод был доступен, но всегда завершался ошибкой NotAllowedError.
НетВ Opera Android с 51 по 88 этот метод был доступен, но всегда завершался ошибкой NotAllowedError. См. ошибку 40418135.
Нет
НетВ Samsung Internet с 11.0 по 88 этот метод был доступен, но всегда завершался ошибкой NotAllowedError. См. ошибку 40418135.
НетВ WebView Android с 72 по 88 этот метод был доступен, но всегда завершался ошибкой NotAllowedError. См. ошибку 40418135.
audio_capture_support
74В Windows и ChromeOS можно захватить весь системный звук при совместном использовании всего экрана. В Linux и macOS можно захватить только звук вкладки.
79В Windows и ChromeOS можно захватить весь системный звук при совместном использовании всего экрана. В Linux и macOS можно захватить только звук вкладки.
Нет
62В Windows и ChromeOS можно захватить весь системный звук при совместном использовании всего экрана. В Linux и macOS можно захватить только звук вкладки.
Нет Нет Нет Нет Нет Нет Нет
controller_option 109 109 Нет 95 Нет Нет Нет Нет Нет Нет Нет
monitorTypeSurfaces_option
119Значение по умолчанию = include
119Значение по умолчанию = include
Нет
105Значение по умолчанию = include
Нет Нет Нет Нет Нет Нет Нет
systemAudio_option
105Значение по умолчанию = include
105Значение по умолчанию = include
Нет
91Значение по умолчанию = include
Нет Нет Нет Нет Нет Нет Нет

См. также

  • API захвата экрана
  • API захвата медиа и потоков
  • Делаем статичные снимки с помощью WebRTC
  • HTMLCanvasElement.captureStream() для получения MediaStream с текущим содержимым <canvas>

© 2005–2024 MDN contributors.
Licensed under the Creative Commons Attribution-ShareAlike License v2.5 or later.
https://developer.mozilla.org/en-US/docs/Web/API/Screen_Capture_API/Using_Screen_Capture

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API