Селфи через JavaScript
В этом уроке мы покажем как через JavaScript можно захватить изображение с телефона, камеры ноутбука или веб-камеры ПК. Задействовать будем различные API, от сторонних библиотек будем держаться подальше — только чистый JavaScript!
Заметка: данное приложение является экспериментальным, не гарантируется работа во всех браузерах. На данный момент не работает на Safari.
Приложение
Для реализации нашей задачи потребуется:
- Осуществить доступ к камере и получить видео поток, используя getUserMedia API.
- Пустить поток с камеры в HTML элемент video.
- При клике по кнопке, сохранить текущий кадр и отобразить его в элементе canvas.
- Преобразовать canvas в изображение dataURL, которое можно скопировать или скачать в формате PNG.
Исходный пример можно получить, нажав на соответствующую кнопку. Так же доступен пример на JSfiddle.
Доступ к камере
В JavaScript есть нативный API для осуществления доступа к камере через метод navigator.getUserMedia. Поскольку данные, сохранённые с камеры считаются сугубо личными, то для работы с данным API вашему сайту потребуется протокол HTTPS.

Если пользователь дал доступ к камере, то метод navigator.getUserMedia передаст видео поток в наш колбэк. Для того чтобы получить видео картинку нужно преобразовать дынный поток через метод createObjectURL .
navigator.getUserMedia( // Настройки < video: true >, // Колбэк для успешной операции function(stream)< // Создаём объект для видео потока и // запускаем его в HTLM элементе video. video.src = window.URL.createObjectURL(stream); // Воспроизводим видео. video.play(); >, // Колбэк для не успешной операции function(err) < // Наиболее частые ошибки — PermissionDenied и DevicesNotFound. console.error(err); >);
Снимок
Теперь когда у нас есть видео поток можем захватить какой-то отдельный кадр через и отобразить его в элементе .
function takeSnapshot() < var hidden_canvas = document.querySelector('canvas'), video = document.querySelector('video.camera_stream'), image = document.querySelector('img.photo'), // Получаем размер видео элемента. width = video.videoWidth, height = video.videoHeight, // Объект для работы с canvas. context = hidden_canvas.getContext('2d'); // Установка размеров canvas идентичных с video. hidden_canvas.width = width; hidden_canvas.height = height; // Отрисовка текущего кадра с video в canvas. context.drawImage(video, 0, 0, width, height); // Преобразование кадра в изображение dataURL. var imageDataURL = hidden_canvas.toDataURL('image/png'); // Помещение изображения в элемент img. image.setAttribute('src', imageDataURL); >
Элемент canvas вполне может быть скрыт и действовать в фоновом режиме.
Загрузка фотографии
Помимо всего этого, мы хотим дать возможность пользователю скачать снимок. Для этого создадим специальную ссылку:
Атрибут download преобразует ссылку в кнопку. Его значение — название скачиваемого файла. Ссылка href на файл в данный момент пуста. Для того чтобы поместить туда изображение нужно чуть переписать код:
function takeSnapshot() < //. // Помещение изображения в элемент img. var imageDataURL = hidden_canvas.toDataURL('image/png'); // Устанавливаем значение атрибуту href. document.querySelector('#dl-btn').href = imageDataURL; >
Теперь после того как снимок будет создан, можно будет скачать файл под названием glorious_selfie.png . Наш небольшой эксперимент завершён!
Итог
Надеемся что данный урок был вам полезен и навёл на мысли о создании фото-видео приложения.
Данный урок подготовлен для вас командой сайта ruseller.com
Источник урока: http://tutorialzine.com/2016/07/take-a-selfie-with-js/
Перевел: Станислав Протасевич
Урок создан: 29 Июля 2016
Просмотров: 38568
Правила перепечатки
5 последних уроков рубрики «jQuery»
Анимация набора текста на jQuery
Сегодня мы бы хотели вам рассказать о библиотеке TypeIt — бесплатном jQuery плагине. С её помощью можно имитировать набор текста. Если всё настроить правильно, то можно добиться очень реалистичного эффекта.
![]()
Временная шкала на jQuery
jQuery плагин для создания временной шкалы.
![]()
Заметка: Перезагрузка и редирект на JavaScript
Быстрая заметка, где вы сможете найти парочку JS сниппетов для перезагрузки и перенаправления пользователей через JavaScript.
Захват кадров с WebRTC
В этой статье объясняется как использовать WebRTC для получения доступа к камере компьютера или мобильного устройства, и захвата кадров с их помощью. Ознакомьтесь с примером, а затем узнайте как это работает.

Перейдите непосредственно к коду на Github , при желании.
Разметка HTML
Наш HTML интерфейс состоит из двух секций : панель отображения видео потока, из которого будет производиться захват и панель отображения результата захвата. Каждая панель имеет свой элемент , для облегчения стилизации и управления.
Все это просто, и мы увидим как они связаны между собой, когда обратимся к коду JavaScript .
Для отображения пользователю результата захвата кадра, в интерфейсе расположен элемент .
Вот и все, что касается HTML. Остальное — просто пух макета страницы и немного текста, предлагающего ссылку на эту страницу.
Код JavaScript
Посмотрим на JavaScript code. Разобьём его на части, для упрощения объяснения.
Инициализация
Начнём с обёртки всего скрипта в анонимную функцию, во избежании конфликтов глобальных переменных, затем инициализируем различные нужные переменные.
(function() < var width = 320; // Этим создадим ширину фотографии var height = 0; // Это будет вычисляться на основе входящего потока var streaming = false; var video = null; var canvas = null; var photo = null; var startbutton = null;
Все переменные выше:
Какой бы не был размер входящего видео, мы намерены масштабировать результирующее изображение к ширине в 320 px.
Результирующая высота изображения будет вычисляться на основе переданной ширины и соотношению сторон потока с камеры.
Указывает на текущую активность видеопотока.
Будет содержать ссылку на элемент после загрузки страницы.
Содержит ссылку на элемент после загрузки страницы.
Содержит ссылку на элемент после загрузки страницы.
Функция startup()
Функция startup() запускается, когда страница закончила загрузку, благодаря установке window.addEventListener() (en-US). Работа функции состоит в том, что бы запросить доступ у пользователя к его камере, инициализировать элемент в значение по умолчанию, и установить обработчики событий, необходимых для получения каждого видеокадра с камеры, запускать захват изображения, при нажатии на кнопку.
Получаем ссылки на элементы
Сначала, получим ссылки на основные элементы, доступ к которым нам необходим.
function startup() < video = document.getElementById('video'); canvas = document.getElementById('canvas'); photo = document.getElementById('photo'); startbutton = document.getElementById('startbutton');
Получаем медиапоток
Следующая задача - получение медиапотока:
navigator.mediaDevices.getUserMedia(< video: true, audio: false >) .then(function(stream) < video.srcObject = stream; video.play(); >) .catch(function(err) < console.log("An error occurred: " + err); >);
Здесь мы называем метод MediaDevices.getUserMedia() , запрашивая медиапоток без аудиопотока ( audio : false ). Он возвращает промис, на котором мы определяем методы успешного и не успешного выполнений.
Успешное выполнение промиса передаёт объект потока( stream ) в качестве параметра функции метода then() ., который присваивается свойству srcObject элемента , направляя поток в него.
Как только поток связан с элементом , запускаем его воспроизведение, вызовом метода HTMLMediaElement.play() .
Метод обработки ошибки промиса вызывается в случае, если получение потока окажется неудачным, к примеру, когда к устройству подключена несовместимая камера, или пользователь запретил к ней доступ.
Обработка события начала воспроизведения
После момента вызова метода HTMLMediaElement.play() на элементе , возникает промежуток времени до начала воспроизведения видеопотока. Для недопущения блокирования интерфейса пользователя в это промежуток, нужно установить обработчик события canplay (en-US) элемента video , который сработает, когда элемент начнёт воспроизведение видеопотока. В этот момент все свойства элемента video конфигурируются на основе формата потока.
video.addEventListener('canplay', function(ev) < if (!streaming) < height = video.videoHeight / (video.videoWidth/width); video.setAttribute('width', width); video.setAttribute('height', height); canvas.setAttribute('width', width); canvas.setAttribute('height', height); streaming = true; >>, false);
Функциональность обработчика не будет запущена, если он запускается повторно. Это отслеживает переменная streaming , которая содержит значение false при первом запуске обработчика.
Если это действительно первый запуск, мы устанавливаем высоту видео на основе разницы в размере между фактическим размером видео - video.videoWidth и шириной, на которую мы собираемся его визуализировать - width
Наконец, свойства width и height элементов video и canvas устанавливаются так, чтобы соответствовать друг другу, вызывая метод Element.setAttribute() на каждом из двух свойств каждого элемента, и, при необходимости, устанавливая ширину и высоту. Наконец, мы установили для переменной streaming значение true , чтобы предотвратить случайное повторное выполнение этого установочного кода.
Обработка нажатий кнопки
Для захвата кадра, пользователь каждый раз нажимает кнопку startbutton , нужно добавить обработчик события кнопки, для его вызова при возникновении события click (en-US) :
startbutton.addEventListener('click', function(ev)< takepicture(); ev.preventDefault(); >, false);
Метод прост, он вызывает функцию takepicture() , определяемую ниже в секции Capturing a frame from the stream, затем вызывает метод Event.preventDefault() на полученном объекте события, для предотвращения действия обработки события более одного раза.
Завершение метода startup()
Ещё пара строк кода в методе startup() :
clearphoto(); >
Вызов метода clearphoto() описывается в секции Clearing the photo box.
Отчистка бокса для фотографии
Очистка бокса фотографии включает создание изображения, а затем преобразование его в формат, используемый элементом , который отображает последний снятый кадр. Код ниже:
function clearphoto() < var context = canvas.getContext('2d'); context.fillStyle = "#AAA"; context.fillRect(0, 0, canvas.width, canvas.height); var data = canvas.toDataURL('image/png'); photo.setAttribute('src', data); >
Наконец, в этой функции мы конвертируем canvas в изображение PNG и вызываем метод photo.setAttribute() отображая захваченный цветовой фон в элементе изображения (бокса для фотографии).
Захват кадра из видеопотока
Последняя функция, требующая определения и являющаяся основным смыслом всего примера - takepicture() , которая захватывает текущий видеокадр, конвертирует его в формат PNG, и отображает его в блоке отображения кадра. Код её ниже:
function takepicture() < var context = canvas.getContext('2d'); if (width && height) < canvas.width = width; canvas.height = height; context.drawImage(video, 0, 0, width, height); var data = canvas.toDataURL('image/png'); photo.setAttribute('src', data); >else < clearphoto(); >>
Как и в случае, когда нам нужно работать с содержимым canvas , мы начинаем с 2D drawing context для скрытого canvas .
Затем, если ширина и высота не равны нулю (имеется в виду, что есть, по крайней мере, потенциально допустимые данные изображения), мы устанавливаем ширину и высоту canvas , чтобы они соответствовали ширине захваченного кадра, затем вызываем метод drawImage() , что бы отрисовать текущий кадр видео в контексте canvas , заполнив весь холст изображением кадра.
Примечание: Используется факт того, что интерфейс HTMLVideoElement похож на интерфейс HTMLImageElement для любых API , которые принимают HTMLImageElement в качестве параметра, с текущим кадром видео, представленным как содержимое изображения.
Как только canvas будет содержать захваченное видео, конвертируем его в PNG формат, вызывая метод HTMLCanvasElement.toDataURL() на нем; наконец вызываем метод photo.setAttribute() отображая захваченное изображение в элементе изображения (бокса фотографии).
Если подходящее изображение не доступно (то есть, width и height равны 0), отчищаем содержимое элемента изображения, вызывая метод clearphoto() .
Приколы с фильтрами
Поскольку мы снимаем изображения с веб-камеры пользователя, захватывая кадры из элемента , можно легко применить фильтры и забавные эффекты к элементу video. Оказывается, любые CSS-фильтры, которые вы применяете к элементу с помощью свойства filter , влияют на захваченную фотографию.Эти фильтры могут варьироваться от простых (делая изображение черно-белым) до экстремальных (размытие по Гауссу и вращение оттенка).
Вы можете экспериментировать с этими эффектами, используя, например, инструмент разработчика FirefoxYou редактор стилей; смотрим Редактирование с CSS фильтрами (en-US) о подробностях выполнения.
Использование определённых устройств
При необходимости вы можете ограничить набор разрешённых источников видео, определённым устройством или набором устройств. Для этого нужно вызвать метод navigator.mediaDevices.enumerateDevices() (en-US). Когда промис разрешиться массивом объектов MediaDeviceInfo (en-US) , описывающих доступные устройства , выберите те, которым хотите разрешить доступ и укажите соответствующий идентификатор устройства deviceId (en-US) или несколько deviceId в объекте MediaTrackConstraints (en-US) , переданном в getUserMedia() .
Смотрите также
- Пробуем пример
- Примеры на Github
- Navigator.mediaDevices.getUserMedia() (en-US)
- Использование изображений
- CanvasRenderingContext2D.drawImage()
Found a content problem with this page?
- Edit the page on GitHub.
- Report the content issue.
- View the source on GitHub.
This page was last modified on 4 авг. 2023 г. by MDN contributors.
Your blueprint for a better internet.
Видеосъёмка из браузера. HTML-код, который включает камеру на смартфоне

Современные стандарты HTML и JavaScript дают разработчикам мощные инструменты для работы со смартфоном через браузер. Мы уже рассказывали о трекинге движений человека по гироскопу/акселерометру с распознаванием паттернов (ходьба, бег, общественный транспорт, нахождение рядом с другим пользователем с аналогичными паттернами) на веб-странице.
Это далеко не единственная такая функция. Например, в мобильных браузерах поддерживается HTML-атрибут , который начинает видеосъёмку на смартфоне просто по нажатию кнопки на веб-странице.
Включение камеры
Согласно таблице, атрибут поддерживается практически всеми популярными мобильными браузерами, кроме Opera Mini. В десктопных браузерах поддержка логично отсутствует, поскольку функция ориентирована конкретно на использование в смартфонах.

Атрибут указывает на запись нового файла (по кнопка выбора файла) и определяет устройство, которое используется для захвата контента. Тип контента определён атрибутом . Значение user означает обращённую к пользователю камеру и/или микрофон, а значение environment — фронтальную.
Пример использования из документации:
Демо (по нажатию кнопки на десктопе открывается диалог выбора файла, а на смартфоне начинается видеозапись)
Логично, что у пользователя не спрашивают разрешение на запись. Во-первых, он должен явно нажать кнопку на веб-странице, на которой написано «Загрузить видео» или «Загрузить фото», после чего начинается фото/видеосъёмка без дополнительных вопросов. Во-вторых, файл сохраняется локально на устройстве пользователя. В-третьих, пользователь явно на экране смартфона видит, что идёт съёмка — и потом должен нажать ещё одну кнопку, чтобы остановить видеозапись и подтвердить результат.
Поэтому телефон и не запрашивает разрешение для веб-страницы на начало записи. Хотя некоторые специалисты по безопасности считают, что реализация оставляет почву для злоупотреблений. В частности, надпись на кнопке может быть ложной. Так что пользователь нажмёт её случайным образом или его подтолкнут к нажатию с помощью обмана.
Сейчас появляется всё больше сайтов, которые делают потрясающие вещи в браузере, захватывая видео через веб-страничку. Для наложения фильтров на видеопоток в реальном времени, видеоконференций, распознавания речи теперь не требуются нативные приложения. Всё это можно делать в браузере на устройстве пользователя. Например, видеопоток можно захватывать и преобразовывать на лету средствами JavaScript MediaDevices API прямо в браузере, см. демо (скриншот на КДПВ).
Другой пример — веб-сайт Critter Camera, который превращает любой смартфон (или компьютер) в камеру наблюдения с детектором движения. То есть его можно оставить на ночь — и браузер сохранит фото, если в комнате произойдёт какое-то движение. Никакая информация не отправляется в интернет, всё хранится в локальном хранилище браузера.

Конечно, функции видеосъёмки «из браузера» добавляют удобства и расширяют функциональность веб-приложений, а пользователя лучше не раздражать лишними запросами на получение разрешений.
В этом есть определённый смысл. Известно, что слишком частые запросы на теряют эффективность — и пользователь начинает разрешать всё подряд без вдумчивого прочтения (принцип действует аналогично баннерной слепоте). Поэтому предупреждений безопасности не должно быть слишком много.
Запись без разрешения
С другой стороны, если пренебрегать запросами на получение разрешений — то возможны злоупотребления. Например, недавно пользователи пожаловались, что бот для распознавания речи Otter.ai записывает конференции Zoom без согласия участников, в то время как по закону для записи приватного разговора нужно получить согласие всех участников.

Бот Otter Assistant подключается ко всем видеоконференциям Zoom в вашем календаре и автоматически публикует текстовые расшифровки
Как можно понять по комментариям, видеозапись видеоконференций происходит после активации функции автоматического распознавания речи у одного из участников чата. После этого речь остальных распознаётся и сохраняется автоматически даже без их согласия. Вероятно, кто-то перепутал согласие на запись разговора и согласие на получение расшифровки.
Сама функция «виртуального ассистента» очень полезная, поскольку позволяет виртуально присутствовать на множестве созвонов — и быстро сканировать текстовое содержание разговоров, что сильно экономит время.
Однако число таких злоупотреблений может расти, если не ограничить их технически, то есть по умолчанию не требовать явного разрешения пользователя. Некоторые разработчики допускают подобные погрешности не из вредоносных побуждений, а просто по незнанию.
Настройки по умолчанию — это зачастую своеобразный компромисс между удобством и безопасностью. В данном случае кажется, что удобство перевешивает.
Зачем разработчики используют сертификаты подписи кода для цифровой подписи приложений и программ читайте здесь.

- HTML
- включение камеры
- Otter.ai
- распознавание речи
- расшифровка видеоконференции
Использование камеры и микрофона в браузере
Код правильный, из книги WebRTC Integrator's Guide. Ни один браузер не спрашивает доступа к камере и не показывает видео. Почему?
Отслеживать
задан 5 мая 2016 в 13:53
11 1 1 серебряный знак 4 4 бронзовых знака
Это нестандартизированные возможности, а значит могут в любой момент поменяться или исчезнуть. В частности в хроме будет работать только в безопасном режиме, в мозиле он mozGetUserMedia и уже устарел, вместо него MediaDevices.getUserMedia(). Ну и прочие причины, по которым плохо работают методы, которые не входят в стандарт.
5 мая 2016 в 14:17
Спасибо, ребята, вы мне очень помогли)
