GetUserMedia: использование API медиазахвата и потоков

25 января 2018

Сегодня я бы хотел поэкспериментировать с API Media Capture и Streams API, разработанным совместно на W3C рабочей группой веб-взаимодействия в режиме реального времени и рабочей группой API устройств. Некоторые разработчики могут знать это просто как getUserMedia, который является основным интерфейсом, который позволяет веб-страницам получать доступ к устройствам захвата мультимедиа, таким как веб-камеры и микрофоны.

Вы можете найти исходный код для этого проекта на моем GitHub. Кроме того, вот вам рабочая демонстрация для экспериментов. В последней версии предварительного просмотра Windows 10 Microsoft впервые добавила поддержку API-интерфейсов захвата мультимедиа в браузере Microsoft Edge. Большая часть этого кода была взята из примера фотозахвата, который команда Edge Dev создала на своем сайте тестового диска.

Для тех из вас, кто хочет погрузиться немного глубже, у Эрика Бидельмана есть отличная статья в HTML5 Rocks, которая входит в легендарную историю этого API.

Начало до скорости

Метод getUserMedia () является хорошей отправной точкой для понимания API-интерфейсов Media Capture. Вызов getUserMedia () принимает MediaStreamConstraints в качестве входного аргумента, который определяет предпочтения и / или требования для устройств захвата и захваченных медиапотоков, таких как обрамление камеры, громкость микрофона и разрешение видео.

Через MediaStreamConstraints вы также можете выбрать конкретное захваченное устройство, используя его deviceId, которое может быть получено из метода enumerateDevices (). После того, как пользователь предоставит разрешение, вызов getUserMedia () вернет обещание с объектом MediaStream, если будут выполнены определенные MediaStreamConstraints.

Все это без необходимости скачивать плагин! В этом примере мы будем погружаться в API и создавать некоторые аккуратные фильтры на видео и изображениях, которые мы будем снимать. Поддерживает ли ваш браузер его? Хорошо, что getUserMedia () работает с Chrome 21, Opera 18 и Firefox 17 и теперь работает в Edge.

Обнаружение функции

Обнаружение функции включает в себя простую проверку наличия navigator.getUserMedia. Это большой проект для проверки в каждом браузере, поэтому я бы предложил просто использовать Modernizr, чтобы проверить его. Вот как это работает:

if (Modernizr.getusermedia) {
  var getUM = Modernizr.prefixed('getUserMedia', navigator);
  getUM({video: true}, function( //...
  //...
}

Без Modernizr, как показано в этом примере, вам нужно будет использовать:

avigator.getUserMedia = navigator.getUserMedia || navigator.webkitGetUserMedia || navigator.mozGetUserMedia;
if (!navigator.getuserMedia) {
  Console.log('You are using a browser that does not support the Media Capture API');
}

Видеопроигрыватель

В нашем HTML вы можете увидеть тег видео вверху страницы. Вы заметите, что он также настроен на автовоспроизведение. Без этого видео будет постоянно заморожено на первом кадре.

<div class="view--video">
    <video id="videoTag" src="" autoplay muted class="view--video__video"></video>
</div> 

Получение доступа к устройству ввода

В настоящее время нет источника для набора носителей, но мы вскоре добавим этот источник через JavaScript.

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

GetUserMedia принимает несколько параметров. Первый - это объект, определяющий детали и требования для каждого типа носителя, к которому вы хотите получить доступ. Для доступа к веб-камере первым параметром должно быть {video: true}. Кроме того, чтобы использовать как микрофон, так и камеру, передайте {video: true, audio: true}.

Поддержка нескольких веб-камер

Это то, что действительно интересно. Мы также используем метод MediaDevices.enumerateDevices в этом примере. Это собирает информацию о доступных устройствах ввода мультимедиа, доступных в вашей системе, таких как микрофоны, камеры и динамики. Это обещание, которое вернет несколько свойств, включая тип (тип) устройства, например, видеовход, аудиоинтерфейс или аудиовыход. Кроме того, он может генерировать уникальный идентификатор в виде строки с уникальным идентификатором (videoinput: id = csO9c0YpAf274OuCPUA53CNE0YHlIr2yXCi + SqfBZZ8 =) и, наконец, ярлык для описания устройства, например, FaceTime HD Camera (встроенный). Это все еще экспериментальная технология, хотя она еще не указана на CanIUse.com.

Установка источника на видеопроигрыватель

В функции initalizeVideoStream вы можете увидеть, что мы получаем видеотег с нашей страницы и устанавливаем его источник в поток, который мы передаем. Сам поток - это blob. Если браузер не поддерживает атрибут srcObject, он возвращается, чтобы создать URL-адрес из медиа-потока и устанавливает его.

// initializeVideoStream() - Callback function when getUserMedia() returns successfully with a mediaStream object
// 1. Set the mediaStream on the video tag
// 2. Use 'srcObject' attribute to determine whether to use the standard-based API or the legacy versio
var initializeVideoStream = function(stream) {
    mediaStream = stream;
    var video = document.getElementById('videoTag');
    if (typeof (video.srcObject) !== 'undefined') {
        video.srcObject = mediaStream;
    }
    else {
        video.src = URL.createObjectURL(mediaStream);
    }
    if (webcamList.length > 1) {
        document.getElementById('switch').disabled = false;
    }
};

Применение фильтров CSS

Я не очень хорошо фотографирую, поэтому часто полагаюсь на фильтры, которые предоставляет Instagram для меня. Но что, если вы можете применить свои собственные фильтры к своему видео или статическому изображению? Ну, ты можешь!

Я создал простую функцию для видеопотока, которая позволяет мне применять фильтры CSS в режиме реального времени. Один для изображения почти идентичен.

// changeCssFiltersOnVid() - Cycle through CSS filters applied to the video stream
// 1. Grab a reference to the video tag
// 2. Keep the original CSS classes while still adding the filters
// 3. Loop through all of the filters
var changeCssFilterOnVid = function () {
    var el       = document.getElementById('videoTag');
    el.className = 'view--video__video';
    var effect = filters[index++ % filters.length]
    if (effect) {
        el.classList.add(effect);
        console.log(el.classList);
    }
}

В верхней части класса у меня есть фильтр фильтров. Они хранятся как строка, которая соответствует классам с одинаковыми именами в CSS.

// CSS filters var index = 0; var filters = ['grayscale', 'sepia', 'blur', 'invert', 'brightness', 'contrast', ''];

И в CSS:

/* image * video filters */
.grayscale {
    -webkit-filter: grayscale(1);
    -moz-filter: grayscale(1);
    -ms-filter: grayscale(1);
    filter: grayscale(1);
}
.sepia {
    -webkit-filter: sepia(1);
    -moz-filter: sepia(1);
    -ms-filter: sepia(1);
    filter: sepia(1);
}
.blur {
    -webkit-filter: blur(3px);
    -moz-filter: blur(3px);
    -ms-filter: blur(3px);
    filter: blur(3px);
}

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

Сохранение изображений

Копание кода, вы можете увидеть некоторые другие функции, с которыми вы не знакомы. Первое, что привлекло мое внимание, было navigator.msSaveBlob. Конструктор Blob позволяет вам легко создавать и манипулировать блобом (в основном файлом) непосредственно на клиенте. Он поддерживается в IE 10+.

Метод msSaveBlob позволяет сохранить этот объект blob (в данном случае, наше изображение моментального снимка) на диск. Он также имеет метод sibling, msSaveOrOpenBlob, который также позволяет вам открывать изображение из браузера.

// savePhoto() - Function invoked when user clicks on the canvas element
// 1. If msSaveBlob is supported, get the photo blob from the canvas and save the image file
// 2. Otherwise, set up the download attribute of the anchor element and download the image file
   var savePhoto = function() {
       if (photoReady) {
           var canvas = document.getElementById('canvasTag');
           if (navigator.msSaveBlob) {
               var imgData = canvas.msToBlob('image/jpeg');
               navigator.msSaveBlob(imgData, 'myPhoto.jpg');
           }
           else {
               var imgData = canvas.toDataURL('image/jpeg');
               var link    = document.getElementById('saveImg');
               link.href   = imgData;
               link.download = 'myPhoto.jpg';
               link.click();
           }
           canvas.removeEventListener('click', savePhoto);
           document.getElementById('photoViewText').ierHTML = '';
           photoReady = false;
       }
   };

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

Где еще мы можем отсюда?

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

Кроме того, вы можете связать себя с API веб-аудио, чтобы применить частотную модуляцию к вашему аудиовыходу. Этот образец из тюнера Web Audio хорошо иллюстрирует его. Некоторые люди больше знакомы с визуальным обучением, поэтому ознакомьтесь с этим примером Microsoft.

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

Не стесняйтесь проверить исходный код и посмотреть рабочий образец.

Больше возможностей с помощью JavaScript

Microsoft имеет кучу бесплатного обучения по многим темам с открытым исходным кодом JavaScript, и мы собираемся создать намного больше с Microsoft Edge. Вот некоторые из них:

Microsoft Edge Web Summit 2015 (полная серия того, что можно ожидать от нового браузера, новых функций веб-платформы и приглашенных ораторов из сообщества) Лучшее из BUILD и Windows 10 (включая новый JavaScript движок для сайтов и приложений). Расширение JavaScript без нарушения работы в Интернете (недавняя заметка Христиана Хейлмана). Хостинг веб-приложений и инноваций в веб-платформе (глубокое погружение на темы, такие как multiple.JS). Практические советы по повышению производительности для вашего JavaScript JavaScript быстрее (семи- серия статей от адаптивного дизайна до казуальных игр для оптимизации производительности) Современная веб-платформа Jump Start (основы HTML, CSS и JavaScript)

И некоторые бесплатные инструменты для запуска: Visual Studio Code, Azure Trial и кросс-браузер инструменты тестирования - все доступно для Mac, Linux или Windows.

Эта статья является частью серии веб-технологий от Microsoft. Мы рады поделиться с вами Microsoft Edge и новым механизмом рендеринга EdgeHTML. Получайте бесплатные виртуальные машины или проверяйте удаленно на своем Mac, iOS, Android или устройстве Windows @ http: dev.modern.ie.