Делайте фотографии и управляйте настройками камеры

Miguel Casas-Sanchez
Франсуа Бофор
François Beaufort

Image Capture — это API для захвата неподвижных изображений и настройки параметров оборудования камеры. Этот API доступен в Chrome 59 на Android и настольных компьютерах. Мы также опубликовали библиотеку полизаполнения ImageCapture .

API позволяет управлять такими функциями камеры, как масштабирование, яркость, контрастность, ISO и баланс белого. Лучше всего то, что Image Capture позволяет вам получить доступ к полному разрешению любой доступной камеры устройства или веб-камеры. Предыдущие методы фотосъемки в Интернете использовали видеоснимки, которые имеют более низкое разрешение, чем разрешение, доступное для неподвижных изображений.

Объект ImageCapture создается с MediaStreamTrack в качестве источника. API имеет два метода захвата takePhoto() и grabFrame() и способы получения возможностей и настроек камеры, а также изменения этих настроек.

Строительство

API захвата изображений получает доступ к камере через MediaStreamTrack , полученный из getUserMedia() :

navigator.mediaDevices.getUserMedia({video: true})
    .then(gotMedia)
    .catch(error => console.error('getUserMedia() error:', error));

function gotMedia(mediaStream) {
    const mediaStreamTrack = mediaStream.getVideoTracks()[0];
    const imageCapture = new ImageCapture(mediaStreamTrack);
    console.log(imageCapture);
}

Вы можете опробовать этот код из консоли DevTools.

Захватывать

Захват может быть выполнен двумя способами: полный кадр и быстрый снимок. takePhoto() возвращает Blob , результат одной фотографической экспозиции , который может быть загружен, сохранен браузером или отображен в элементе <img> . Этот метод использует максимально возможное разрешение фотокамеры. Например:

const img = document.querySelector('img');
// ...
imageCapture.takePhoto()
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('takePhoto() error:', error));

grabFrame() возвращает объект ImageBitmap , снимок живого видео , который может (например) быть нарисован на <canvas > и затем подвергнут постобработке для выборочного изменения цветовых значений. Обратите внимание, что ImageBitmap будет иметь только разрешение источника видео — которое обычно ниже возможностей камеры по созданию неподвижных изображений. Например:

const canvas = document.querySelector('canvas');
// ...
imageCapture.grabFrame()
    .then(imageBitmap => {
    canvas.width = imageBitmap.width;
    canvas.height = imageBitmap.height;
    canvas.getContext('2d').drawImage(imageBitmap, 0, 0);
    })
    .catch(error => console.error('grabFrame() error:', error));

Возможности и настройки

Существует несколько способов манипулирования настройками захвата, в зависимости от того, будут ли изменения отражены в MediaStreamTrack или их можно будет увидеть только после takePhoto() . Например, изменение уровня zoom немедленно распространяется на MediaStreamTrack , тогда как подавление эффекта красных глаз, если установлено, применяется только во время фотосъемки.

Возможности и настройки "живой" камеры управляются через предварительный просмотр MediaStreamTrack : MediaStreamTrack.getCapabilities() возвращает словарь MediaTrackCapabilities с конкретными поддерживаемыми возможностями и диапазонами или допустимыми значениями, например, поддерживаемый диапазон масштабирования или допустимые режимы баланса белого. Соответственно, MediaStreamTrack.getSettings() возвращает MediaTrackSettings с конкретными текущими настройками. Масштабирование, яркость и режим фонарика относятся к этой категории, например:

var zoomSlider = document.querySelector('input[type=range]');
// ...
const capabilities = mediaStreamTrack.getCapabilities();
const settings = mediaStreamTrack.getSettings();
if (capabilities.zoom) {
    zoomSlider.min = capabilities.zoom.min;
    zoomSlider.max = capabilities.zoom.max;
    zoomSlider.step = capabilities.zoom.step;
    zoomSlider.value = settings.zoom;
}

Возможности и настройки камеры "Non-Live" управляются через объект ImageCapture : ImageCapture.getPhotoCapabilities() возвращает объект PhotoCapabilities , который предоставляет доступ к доступным возможностям камеры "Non-Live". Соответственно, начиная с Chrome 61, ImageCapture.getPhotoSettings() возвращает объект PhotoSettings с конкретными текущими настройками. Разрешение фото, устранение эффекта красных глаз и режим вспышки (кроме фонарика) относятся к этому разделу, например:

var widthSlider = document.querySelector('input[type=range]');
// ...
imageCapture.getPhotoCapabilities()
    .then(function(photoCapabilities) {
    widthSlider.min = photoCapabilities.imageWidth.min;
    widthSlider.max = photoCapabilities.imageWidth.max;
    widthSlider.step = photoCapabilities.imageWidth.step;
    return imageCapture.getPhotoSettings();
    })
    .then(function(photoSettings) {
    widthSlider.value = photoSettings.imageWidth;
    })
    .catch(error => console.error('Error getting camera capabilities and settings:', error));

Настройка

Параметры «живой» камеры можно настроить с помощью ограничений applyConstraints() предварительного просмотра MediaStreamTrack , например:

var zoomSlider = document.querySelector('input[type=range]');

mediaStreamTrack.applyConstraints({ advanced: [{ zoom: zoomSlider.value }]})
    .catch(error => console.error('Uh, oh, applyConstraints() error:', error));

Настройки «неживой» камеры настраиваются с помощью необязательного словаря PhotoSettings takePhoto() , например:

var widthSlider = document.querySelector('input[type=range]');
imageCapture.takePhoto({ imageWidth : widthSlider.value })
    .then(blob => {
    img.src = URL.createObjectURL(blob);
    img.onload = () => { URL.revokeObjectURL(this.src); }
    })
    .catch(error => console.error('Uh, oh, takePhoto() error:', error));

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

Если вы запустите приведенный выше код, вы заметите разницу в размерах между результатами grabFrame() и takePhoto() .

Метод takePhoto() предоставляет доступ к максимальному разрешению камеры.

grabFrame() просто берет следующий доступный VideoFrame в MediaStreamTrack внутри процесса рендеринга, тогда как takePhoto() прерывает MediaStream , перенастраивает камеру, делает фотографию (обычно в сжатом формате, отсюда и Blob ) и затем возобновляет MediaStreamTrack . По сути, это означает, что takePhoto() дает доступ к полным возможностям разрешения неподвижных изображений камеры. Раньше можно было «сделать фотографию», только вызвав drawImage() на элементе canvas , используя видео в качестве источника (как в примере здесь ).

Более подробную информацию можно найти в разделе README.md.

В этой демонстрации размеры <canvas> задаются в соответствии с разрешением видеопотока, тогда как естественный размер <img> — это максимальное разрешение неподвижного изображения камеры. CSS, конечно, используется для установки размера отображения обоих.

Полный диапазон доступных разрешений камеры для неподвижных изображений можно получить и задать с помощью значений MediaSettingsRange для PhotoCapabilities.imageHeight и imageWidth . Обратите внимание, что минимальные и максимальные ограничения ширины и высоты для getUserMedia() предназначены для видео, которые (как обсуждалось) могут отличаться от возможностей камеры для неподвижных изображений. Другими словами, вы не сможете получить доступ к полным возможностям разрешения вашего устройства при сохранении из getUserMedia() на холст. Демонстрация ограничений разрешения WebRTC показывает, как задать ограничения getUserMedia() для разрешения.

Что-нибудь еще?

  • API распознавания формы хорошо работает с захватом изображения: grabFrame() можно вызывать многократно для передачи ImageBitmap в FaceDetector или BarcodeDetector . Узнайте больше об API из записи в блоге Пола Кинлана.

  • Вспышку камеры (подсветку устройства) можно открыть через FillLightMode в PhotoCapabilities , а режим Torch (постоянно включенная вспышка) можно найти в MediaTrackCapabilities .

Демонстрации и примеры кода

Поддерживать

  • Chrome 59 на Android и ПК.
  • Chrome Canary на Android и ПК до версии 59 с включенными функциями экспериментальной веб-платформы .

Узнать больше