[Перевод] Использование Media Capture API в браузере

Предлагаю читателям «Хабрахабра» перевод статьи «Using the Media Capture API in the Browser» авторства Dave Voyles.

a19a544fc80e491f98535a2a0bc03205.jpg

Сегодня я хочу поэксперементировать с Media Capture и Streams API, разработанные совместно в Web Real-Time Communications Working Group из W3C и Device APIs Working Group. Некоторые разработчики могут знать их как getUserMedia — главный интерфейс, который позврляет веб-страницам получать доступ к таким девайсам, как веб-камеры и микрофоны.
Вы можете найти исходный код проекта в моем GitHub. Здесь есть рабочие демо для ваших эксперементов. В последнем Windows 10 preview release Microsoft впервые добавила поддержку media capture APIs в Microsoft Edge. Значительная часть кода из примера взята с Photo Capture sample, который сделала команда разработчиков Edge на их тестовом сайте.

Для тех из вас, кто хочет узнать чуть болше, Eric Bidelman написал отличную статью на HTML5 rocks, которая рассказывает историю этих API.


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

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

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


Функция обнаружения — простоя проверка существования navigator.getUserMedia. Это большая работа — проверить каждый браузер. Я советую использовать Modernizr. Вот как это работает:

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


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

  navigator.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 вы можете поместить video тег вверху страницы. Вы можете заметить, что он стоит на autoplay`е. Без этого, зависнет на первом кадре.


Здесь еще нет медиа источника, но мы сделаем с помощью Javascript.
Новый функционал может дать разработчикам несколько новых возможностей, но тут есть риск в отношении безопасности пользователя, следовательно первое что происходит при запуске веб приложения — запрос разрешения пользователя на доступ к устройству захвата. getUserMedia принимает несколько параметров. Первый — объект указывающий детали и требования для каждого типа медиа, к которым вы хотите получит доступ. Для доступа к камере первый параметр должен быть {video: true}, для использования и камеры и микрофона {video: true, audio: true}.

7dcfacaa1ded43cfb6e83f4b93a3ca9b.jpg


Вот здесь реально становиться интерестно. Мы также используем MediaDevices.enumeratedDevices метод в этом примере. Он собирет информацию про устройства ввода-вывода, доступные в вашей системе, такие как микрофоны, камеры, колонки. Это обещание может вернуть несколько свойств включая вид (тип) устройства: «videoinput», «audioinput», или «audiooutput.» Дополнительно он может сгенерировать уникальный ID в форме строки (videoinput: id = csO9c0YpAf274OuCPUA53CNE0YHlIr2yXCi+SqfBZZ8=), метку с описанием устройства, к примеру: «FaceTime HD Camera (Built-in)». Эта технология остается экспериментальной, и ее еще нет на CanIUse.com.
В initalizeVideoStream функции вы можете увидеть, что мы берем video тег со страницы и устанавливаем его источником наш стрим. Стрим сам по себе — blob. Если браузер не поддерживает srcObject атрибут, надо сделать URL для медиа стрима и установить его.

    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;
        }
    };


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

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

    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 фильтры 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 test drive page.


Разбираясь в коде, вы могли заметить несколько вещей, которые вам не знакомы. Первой вещью, которая притянула мой взгляд была navigator.msSaveBlob. Blob конструктор позволяет вам легко создавать и манипулировать blob`ом прямо на клиенте. Он поддерживается в IE 10+.

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

  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').innerHTML = '';
            photoReady = false;
        }
    };

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


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

Дополнительно вы можете привязать Web Audio API, чтобы применить частотную модуляцию к аудио потоку. Этот пример из Web Audio tuner`а отлично это демонстрирует. Некоторым проще воспринимать визуально, так что проверьте пример от Microsoft.

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

По всем найденым ошибкам просьба сообщать в лс.

© Habrahabr.ru