<usermedia> — новый HTML элемент

от автора

Эта статья — перевод оригинальной статьи «Introducing the <usermedia> HTML element».

Также я веду телеграм канал «Frontend по‑флотски», где рассказываю про интересные вещи из мира разработки интерфейсов и AI.

Вступление

После появления элемента <geolocation> в Chrome 144 следующим функциональным элементом набора Capability Elements стал HTML-элемент <usermedia>. Он доступен начиная с Chrome 151 и знаменует следующий этап перехода от универсальных запросов разрешений к специализированным элементам управления доступом к потокам с камеры и микрофона.

Вместо запросов, которые вызываются из JavaScript, <usermedia> предлагает декларативный подход, при котором действие инициирует сам пользователь. Это позволяет сократить объём шаблонного кода, повысить безопасность и упростить повторный запрос доступа для пользователей, которые ранее его запретили. Тем самым элемент решает давнюю проблему, связанную с восстановлением отклонённых разрешений.

От управления разрешениями — к управлению возможностями

Элемент <usermedia> стал следующим специализированным элементом управления в наборе Capability Elements после успешного запуска <geolocation>. Переход от изначального универсального элемента <permission>, предложенного в рамках инициативы PEPC, позволяет браузеру эффективнее учитывать особенности и поведение различных аппаратных возможностей.

Раннее предложение было сосредоточено главным образом на управлении состояниями разрешений — например, разрешить или запретить доступ. Capability Elements работают иначе: они выступают посредниками при передаче данных.

Элемент <geolocation> предоставляет сайту объект с данными о местоположении, а <usermedia> управляет всем процессом доступа к камере и микрофону. Он фиксирует намерение пользователя, управляет системным запросом браузера и передаёт приложению объект MediaStream.

Благодаря этому больше не нужно отдельно вызывать getUserMedia(), реализация становится проще, а браузер получает надёжный сигнал о том, что пользователь действительно хочет предоставить доступ.

Проверка концепции

Данные, полученные в ходе первого Origin Trial, показали, что контекстные элементы управления разрешениями, активируемые самим пользователем, значительно повышают вероятность успешного предоставления доступа.

  • Cisco выяснила, что среди пользователей, которые изначально отклонили запрос разрешения, лишь около 10% впоследствии успешно предоставляли доступ через традиционные системные окна. При использовании нового элемента этот показатель вырос более чем до 65%.

  • Zoom сообщила о снижении числа ошибок при доступе к камере и микрофону на 46,9%. Речь, в частности, об ограничениях на уровне операционной системы. Новый элемент помогал направлять пользователей по сценарию восстановления доступа.

  • В Google Meet количество отзывов в духе «микрофон не работает» сократилось на 17%, а число успешных восстановлений разрешений среди пользователей, которые первоначально запретили доступ, выросло на 131%.

Зачем использовать элемент <usermedia>?

Продолжая подход, заложенный в <geolocation>, элемент <usermedia> решает основные проблемы, связанные с запросом доступа к чувствительным возможностям браузера. Сейчас доступ к камере и микрофону запрашивается с помощью императивных вызовов JavaScript, из-за чего системные окна нередко появляются вне понятного пользователю контекста. А если пользователь случайно запретил сайту доступ, для отмены этого решения приходится искать нужный пункт глубоко в настройках браузера. Эта «ловушка разрешений» часто приводит к тому, что пользователь просто отказывается от функции.

Элемент <usermedia> решает эти проблемы следующим образом.

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

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

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

Аспекты

JavaScript API getUserMedia()

HTML-элемент <usermedia>

Что запускает запрос разрешения

Императивный вызов из скрипта (getUserMedia)

Пользователь нажимает на элемент, управляемый браузером

Роль браузера

Решает, показывать ли запрос, с учётом текущего состояния и внутренних эвристик

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

Ответственность сайта

Вручную вызвать JavaScript API, обработать колбэки и возможные ошибки

Подписаться на событие stream и получить поток через свойство stream

Основная задача

Базовый доступ к камере и микрофону

Получение медиапотока, управление разрешениями и восстановление доступа с меньшим количеством лишних действий

Реализация

Интеграция нового элемента требует значительно меньше шаблонного кода, чем использование традиционного JavaScript API. Следуя декларативному подходу, заложенному в <geolocation>, достаточно добавить тег <usermedia> в HTML и настроить требования к оборудованию с помощью метода setConstraints().

Примечание. В этом материале предполагается, что браузер поддерживает элемент <usermedia>. Вариант реализации для браузеров без такой поддержки описан далее, в разделе «Собственный механизм резервной обработки».

<usermedia id="media-ctrl">  <button>Включи камеру и микрофон</button></usermedia>
const el = document.getElementById('media-ctrl');// Укажите требования к оборудованию до взаимодействия пользователя:el.setConstraints({    video: { width: 1280, height: 720 },    audio: { echoCancellation: true }});// Обработайте успешное получение медиапотока:el.addEventListener('stream', () => {  videoPreview.srcObject = el.stream;});// Обработайте ошибку при получении медиапотока:el.addEventListener('error', () => {  console.error(`Access failed: ${el.error?.name}`);});// Обработайте отмену или закрытие запроса разрешения:el.addEventListener('cancel', () => {  console.log('Permission prompt was dismissed by the user.');});

Основные атрибуты и свойства:

  • stream — свойство только для чтения, которое содержит объект MediaStream после того, как пользователь успешно предоставил доступ.

  • setConstraints() — метод, позволяющий задать или обновить требования к оборудованию, например deviceId или разрешение видео, до того, как пользователь начнёт взаимодействовать с элементом.

  • error — свойство только для чтения, которое возвращает объект DOMException, например NotAllowedError, если запрос завершился ошибкой или был отклонён.

  • onstream — обработчик события, который вызывается сразу после получения медиатреков.

  • onerror — обработчик события, который вызывается, если получить медиапоток не удалось.

  • oncancel — обработчик события, который вызывается, когда пользователь отменяет запрос или закрывает окно разрешения во время получения доступа.

Ограничения на стилизацию

Чтобы сохранить доверие пользователя и не допустить использования вводящих в заблуждение интерфейсных приёмов, для элемента <usermedia> действуют те же строгие ограничения на оформление, что и для других Capability Elements.

Читаемость. Браузер проверяет, достаточно ли контрастны цвет текста и фон. Минимальное соотношение контрастности составляет 3:1, чтобы содержимое элемента всегда оставалось читаемым. Альфа-канал, то есть непрозрачность, должен быть равен 1, чтобы элемент нельзя было сделать незаметным или полупрозрачным.

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

Целостность внешнего вида. Браузер ограничивает эффекты, способные исказить элемент. Например, свойство transform поддерживает только двумерное перемещение и пропорциональное масштабирование.

CSS-псевдоклассы. Элемент поддерживает стилизацию в зависимости от состояния. Например, псевдокласс :granted применяется после предоставления разрешения и успешного получения медиапотока. Также доступны стандартные состояния взаимодействия, такие как :hover и :active.

Прогрессивное улучшение и стратегия миграции

Следуя подходу, заложенному в <geolocation>, элемент <usermedia> спроектирован так, чтобы корректно работать и в браузерах без его поддержки. Такие браузеры воспримут его как HTMLUnknownElement и отобразят вложенное содержимое. Благодаря этому можно предусмотреть запасной сценарий для всех пользователей.

Собственный механизм резервной обработки

Определить поддержку элемента <usermedia> в JavaScript можно программно:

if ('HTMLUserMediaElement' in window) {  // Используем современный <usermedia>} else {  // Фолбэк к старому getUserMedia() API}

Используйте эту проверку, чтобы добавить внутрь элемента <usermedia> обычную кнопку, которая будет вызывать устаревший API getUserMedia():

<usermedia id="stream-handler">    <button id="fallback-stream-handler">        Включи камеру и микрофон    </button></usermedia>
// Функция для управления видео/аудио потоками:function handleStream (event) {  /* ... */}if ('HTMLUserMediaElement' in window) {  // В таком случае можем использовать <usermedia>:  const streamHandler = document.getElementById('stream-handler');  streamHandler.addEventListener('stream', event => {    handleStream(event);  });} else {  // <usermedia> не поддерживается, делаем фоллбэк:  const fallbackStreamHandler = document.getElementById('fallback-stream-handler');  fallbackStreamHandler.addEventListener('click', event => {    navigator.mediaDevices.getUserMedia({video: true, audio: true}).then(handleStream);  });}

Миграция для участников Origin Trial

Для разработчиков, которые во время Origin Trial интегрировали экспериментальный универсальный элемент <permission>, переход на <usermedia> потребует минимальных изменений.

Обновление тега. Замените <permission type="camera microphone"> на <usermedia>. Также обновите все селекторы, которые обращались к элементам <permission>, чтобы теперь они использовали <usermedia>.

Проверка поддержки. Замените проверки HTMLPermissionElement на HTMLUserMediaElement.

Что дальше

Сейчас элемент <usermedia> предназначен для одновременного запроса доступа к аудио и видео. В дальнейшем набор Capability Elements планируется расширить следующими элементами:

  • <camera> — для сценариев, в которых требуется только видео;

  • <microphone> — для сценариев, в которых требуется только аудио.

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

ссылка на оригинал статьи https://habr.com/ru/articles/1065336/