aboutsummaryrefslogtreecommitdiff
path: root/files/ru/web/api/webrtc_api/taking_still_photos/index.html
diff options
context:
space:
mode:
authorPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
committerPeter Bengtsson <mail@peterbe.com>2020-12-08 14:42:52 -0500
commit074785cea106179cb3305637055ab0a009ca74f2 (patch)
treee6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/ru/web/api/webrtc_api/taking_still_photos/index.html
parentda78a9e329e272dedb2400b79a3bdeebff387d47 (diff)
downloadtranslated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz
translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2
translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip
initial commit
Diffstat (limited to 'files/ru/web/api/webrtc_api/taking_still_photos/index.html')
-rw-r--r--files/ru/web/api/webrtc_api/taking_still_photos/index.html222
1 files changed, 222 insertions, 0 deletions
diff --git a/files/ru/web/api/webrtc_api/taking_still_photos/index.html b/files/ru/web/api/webrtc_api/taking_still_photos/index.html
new file mode 100644
index 0000000000..ec5e7ec42d
--- /dev/null
+++ b/files/ru/web/api/webrtc_api/taking_still_photos/index.html
@@ -0,0 +1,222 @@
+---
+title: Захват кадров с WebRTC
+slug: Web/API/WebRTC_API/Taking_still_photos
+tags:
+ - Захват WebRTC
+translation_of: Web/API/WebRTC_API/Taking_still_photos
+---
+<p dir="rtl"><span><span><span><span>{{WebRTCSidebar}}</span></span></span></span></p>
+
+<p><span class="seoSummary"><span><span><span><span>В этой статье объясняется как использовать WebRTC для получения доступа к камере компьютера или мобильного устройства, и захвата кадров с их помощью. </span></span></span></span></span><a href="https://mdn-samples.mozilla.org/s/webrtc-capturestill"><span><span><span><span>Ознакомтесь с примером,</span></span></span></span></a><span><span><span><span> а затем узнайте как это работает.</span></span></span></span></p>
+
+<p><img alt="Uz WebRTC balstīta attēla uztveršanas lietotne - kreisajā pusē un bez tīmekļa kameras uzņemšanas video straumē un poga" src="https://mdn.mozillademos.org/files/10281/web-rtc-demo.png" style="display: block; height: 252px; margin: 0 auto; width: 677px;"></p>
+
+<p><span><span><span><span>Перейдите непостредственно </span></span></span></span><a class="external" href="https://github.com/mdn/samples-server/tree/master/s/webrtc-capturestill" rel="noopener"><span><span><span><span>к коду на Github</span></span></span></span></a><span><span><span><span> , при желании.</span></span></span></span></p>
+
+<h2 id="Разметка_HTML"><span><span><span><span>Разметка HTML</span></span></span></span></h2>
+
+<p><a class="external" href="https://github.com/mdn/samples-server/tree/master/s/webrtc-capturestill/index.html" rel="noopener"><span><span><span><span>Наш HTML интерфейс</span></span></span></span></a><span><span><span><span> состоит из двух секций : панель отображения видео потока, из которого будет производиться захват и панель отображения результата захвата. Каждая панель имеет свой элемент </span></span></span><span><span><span>{{HTMLElement ("div")}}, для облегчения стилизации и управления.</span></span></span></span></p>
+
+<p><span><span><span><span>Первая панель слева содержит два компонента : элемент {{HTMLElement ("video")}} , который будет получать поток, отводимый с камеры, и элемент  </span></span></span></span>{{HTMLElement("button")}}, каторый будет использоваться пользователем для активации захвата видео кадра.</p>
+
+<pre>  &lt;div class="camera"&gt;
+    &lt;video id="video"&gt;Video stream not available.&lt;/video&gt;
+    &lt;button id="startbutton"&gt;Take photo&lt;/button&gt;
+  &lt;/div&gt;</pre>
+
+<p>Все это просто, и мы увидим как они связаны между собой, когда обратимся к коду  JavaScript .</p>
+
+<p>В разметке имеется элемент {{HTMLElement("canvas")}} , который сохраняет захваченный кадр, который может быть дополнительно обработан и конвертируется в выходной файл изображения. Элемент<code> canvas </code>является скрытым, в его стиле свойство {{cssxref("display")}}<code>:none</code>, во избежании поломки интерфейса, где пользователю совершенно не обязательно видеть служебные элементы.</p>
+
+<p>Для отображения пользователю результата захвата кадра, в интерфейсе расположен элемент {{HTMLElement("img")}}.</p>
+
+<pre>  &lt;canvas id="canvas"&gt;
+  &lt;/canvas&gt;
+  &lt;div class="output"&gt;
+    &lt;img id="photo" alt="The screen capture will appear in this box."&gt;
+  &lt;/div&gt;</pre>
+
+<p>Вот и все, что касается HTML. Остальное - просто пух макета страницы и немного текста, предлагающего ссылку на эту страницу.</p>
+
+<h2 id="Код_JavaScript">Код JavaScript</h2>
+
+<p>Посмотрим на  <a href="https://github.com/mdn/samples-server/tree/master/s/webrtc-capturestill/capture.js" rel="noopener">JavaScript code</a>. Разобъем его на части, для упрощения объяснения.</p>
+
+<h3 id="Инициализация">Инициализация</h3>
+
+<p>Начнем с обертки всего скрипта в анонимную функцию, во избежании конфликтов глобальных переменных, затем инициализируем различные нужные  переменные.</p>
+
+<pre>(function() {
+ var width = 320; // Этим создадим ширину фотографии
+ var height = 0; // Это будет вычисляться на основе входящего потока
+
+ var streaming = false;
+
+ var video = null;
+ var canvas = null;
+ var photo = null;
+ var startbutton = null;</pre>
+
+<p>Все переменные выше:</p>
+
+<dl>
+ <dt><code>width</code></dt>
+ <dd>Какой бы не был размер входящего видео, мы намерены масштабировать результирующее изображение к ширине в 320 px.</dd>
+ <dt><code>height</code></dt>
+ <dd>Результирующая высота изображения будет вычисляться на основе переданной ширины и соотношению сторон потока с камеры.</dd>
+ <dt><code>streaming</code></dt>
+ <dd>Указывает на текущую активность видеопотока.</dd>
+ <dt><code>video</code></dt>
+ <dd>Будет содержать ссылку на элемент {{HTMLElement("video")}}  после загрузки страницы.</dd>
+ <dt><code>canvas</code></dt>
+ <dd>Содержит ссылку на элемент  {{HTMLElement("canvas")}} после загрузки страницы.</dd>
+ <dt><code>photo</code></dt>
+ <dd>Содержит ссылку на элемент  {{HTMLElement("img")}} после загрузки страницы.</dd>
+ <dt><code>startbutton</code></dt>
+ <dd>Содержит ссылку на элемент  {{HTMLElement("button")}} после загрузки страницы, используюется для старта захвата.</dd>
+</dl>
+
+<h3 id="Функция_startup">Функция  startup()</h3>
+
+<p>Функция <code>startup()</code> запускается, когда страница закончила загрузку, благодаря установке {{domxref("window.addEventListener()")}}. Работа функции состоит в том, что бы запросить доступ у пользователя к его камере, инициализировать элемент  {{HTMLElement("img")}} в значение по умолчанию, и установить обработчики событий, необходимых для получения каждого видеокадра с камеры, запускать захват изображения, при нажатии на кнопку.</p>
+
+<h4 id="Получаем_ссылки_на_элементы">Получаем ссылки на элементы</h4>
+
+<p>Сначала, получим ссылки на основные элементы, доступ к которым нам необходим.</p>
+
+<pre> function startup() {
+ video = document.getElementById('video');
+ canvas = document.getElementById('canvas');
+ photo = document.getElementById('photo');
+ startbutton = document.getElementById('startbutton');</pre>
+
+<h4 id="Получаем_медиапоток">Получаем медиапоток </h4>
+
+<p>Следующая задача - получение медиапотока:</p>
+
+<pre> navigator.mediaDevices.getUserMedia({ video: true, audio: false })
+ .then(function(stream) {
+ video.srcObject = stream;
+ video.play();
+ })
+ .catch(function(err) {
+ console.log("An error occurred: " + err);
+ });
+</pre>
+
+<p>Здесь мы вазываем метод  {{domxref("MediaDevices.getUserMedia()")}} , запрашивая медиапоток без аудиопотока (<code>audio : false</code>). Он возвращает промис, на котором мы определяем методы успешного и не успешного выполнений.</p>
+
+<p>Успешное выполнение промиса передает объект потока( <code>stream</code> ) в качестве параметра функции метода <code>then()</code>., который присваевается свойству <code>srcObject</code> элемента {{HTMLElement("video")}}, направляя поток в него.</p>
+
+<p>Как только поток связан с элементом <code>&lt;video&gt;</code> ,  запускаем его воспроизведение, вызовом метода <code><a href="https://wiki.developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement#play">HTMLMediaElement.play()</a></code>.</p>
+
+<p>Метод обработки ошибки промиса  вызывается в случае, если получение потока окажется неудачным, к примеру, когда к устройству подключена несовместимая камера, или пользователь запретил к ней доступ.</p>
+
+<h4 id="Обработка_события_начала_воспроизведения">Обработка события начала воспроизведения</h4>
+
+<p>После момента вызова метода  <code><a href="https://developer.mozilla.org/en-US/docs/Web/API/HTMLMediaElement#play">HTMLMediaElement.play()</a></code> на элементе {{HTMLElement("video")}}, возникает промежуток времени до начала воспроизведения видеопотока. Для недопущения блокирования интерфейса пользователя в это промежуток, нужно установить обработчик события {{event("canplay")}} элемента <code>video</code> , который сработает, когда элемент начнет воспроизведение видеопотока. В этот момент все свойства элемента <code>video</code> конфигурируются на основе формата потока.</p>
+
+<pre> 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);</pre>
+
+<p>Функциональность обработчика не будет запущена, если он запускается повторно. Это отслеживает переменная <code>streaming</code> , которая содержит значение  <code>false</code> при первом запуске обработчика.</p>
+
+<p>Если это действительно первый запуск, мы устанавливаем высоту видео на основе разницы в размере между фактическим размером видео - <code>video.videoWidth</code> и шириной, на которую мы собираемся его визуализировать - <code>width</code></p>
+
+<p>Наконец, свойства <code>width</code> и <code>height</code> элементов<code> video</code> и <code>canvas</code> устанавливаются так, чтобы соответствовать друг другу, вызывая метод {{domxref("Element.setAttribute()")}} на каждом из двух свойств каждого элемента, и, при необходимости, устанавливая ширину и высоту. Наконец, мы установили для  переменной <code>streaming</code> значение <code>true</code>, чтобы предотвратить случайное повторное выполнение этого установочного кода.</p>
+
+<h4 id="Обработка_нажатий_кнопки">Обработка нажатий кнопки</h4>
+
+<p>Для захвата кадра, пользователь каждый раз нажимает кнопку  <code>startbutton</code>, нужно добавить обработчик события кнопки, для его вызова при возникновении события  {{event("click")}} :</p>
+
+<pre> startbutton.addEventListener('click', function(ev){
+ takepicture();
+ ev.preventDefault();
+ }, false);</pre>
+
+<p>Метод прост, он вызывает функцию  <code>takepicture()</code>, определяемую ниже в секции  {{anch("Capturing a frame from the stream")}}, затем вызывает метод {{domxref("Event.preventDefault()")}} на полученном объекте события, для предотвращения действия обработки события более одного раза.</p>
+
+<h4 id="Завершение_метода_startup">Завершение метода  startup() </h4>
+
+<p>Еще пара строк кода в методе <code>startup()</code>:</p>
+
+<pre> clearphoto();
+ }</pre>
+
+<p>Вызов метода <code>clearphoto()</code> описывается в секции {{anch("Clearing the photo box")}}.</p>
+
+<h3 id="Отчистка_бокса_для_фотографии">Отчистка бокса для фотографии</h3>
+
+<p>Очистка бокса фотографии включает создание изображения, а затем преобразование его в формат, используемый элементом {{HTMLElement ("img")}}, который отображает последний снятый кадр. Код ниже:</p>
+
+<pre> 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);
+ }</pre>
+
+<p>Начнем с получения ссылки на скрытый элемент {{HTMLElement ("canvas")}}, который мы используем для рендеринга за пределами экрана. Затем мы устанавливаем свойсто <code>fillStyle</code> в  <code>#AAA</code> ( светло-серый) и заполняем весь холст этим цветом, вызывая метод {{domxref("CanvasRenderingContext2D.fillRect()","fillRect()")}}.</p>
+
+<p>Наконец, в этой функции мы конвертируем <code>canvas</code> в изображение PNG и вызываем метод <code>{{domxref("Element.setAttribute", "photo.setAttribute()")}}</code> отображая захваченный цветовой фон в элементе изображения (бокса для фотографии).</p>
+
+<h3 id="Захват_кадра_из_видеопотока">Захват кадра из видеопотока</h3>
+
+<p>Последняя функция, требующая определения и являющаяся основным смыслом всего примера - <code>takepicture()</code> , которая захватывает текущий видеокадр, конвертирует его в формат PNG, и отображает его в блоке отображения кадра. Код её ниже:</p>
+
+<pre> function takepicture() {
+ var context = canvas.getContext('2d');
+ if (width &amp;&amp; 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();
+ }
+ }</pre>
+
+<p>Как и в случае, когда нам нужно работать с содержимым <code>canvas</code>, мы начинаем с {{domxref("CanvasRenderingContext2D","2D drawing context")}}  для скрытого <code>canvas</code>.</p>
+
+<p>Затем, если ширина и высота не равны нулю (имеется в виду, что есть, по крайней мере, потенциально допустимые данные изображения), мы устанавливаем ширину и высоту <code>canvas</code>, чтобы они соответствовали ширине захваченного кадра, затем вызываем метод {{domxref("CanvasRenderingContext2D.drawImage()", "drawImage()")}} , что бы отрисовать текущий кадр видео в контексте <code>canvas</code>, заполнив весь холст изображением кадра.</p>
+
+<div class="blockIndicator note">
+<p><strong>Примечание :</strong> Используется факт того, что интерфейс {{domxref("HTMLVideoElement")}} похож на интерфейс {{domxref("HTMLImageElement")}} для любых API , которые принимают <code>HTMLImageElement</code> в качестве параметра, с текущим кадром видео, представленным как содержимое изображения.</p>
+</div>
+
+<p>Как тоько  <code>canvas</code> будет содержать захваченное видео, конвертируем его в  PNG формат, вызывая метод {{domxref("HTMLCanvasElement.toDataURL()")}} на нем; наконец вызываем метод {{domxref("Element.setAttribute", "photo.setAttribute()")}} отображая захваченное изображение в элементе изображения (бокса фотографии).</p>
+
+<p>Если подходящее изображение не доступно (то есть, <code>width</code> и <code>height</code> равны  0), отчищаем содержимое элемента изображения, вызывая метод <code>clearphoto()</code>.</p>
+
+<h2 id="Приколы_с_фильтрами">Приколы с фильтрами</h2>
+
+<p>Поскольку мы снимаем изображения с веб-камеры пользователя, захватывая кадры из элемента {{HTMLElement("video")}} , можно легко применить фильтры и забавные эффекты к элементу <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">video</span></font>. Оказывается, любые CSS-фильтры, которые вы применяете к элементу с помощью свойства {{cssxref ("filter")}}, влияют на захваченную фотографию.Эти фильтры могут варьироваться от простых (делая изображение черно-белым) до экстремальных (размытие по Гауссу и вращение оттенка).</p>
+
+<p>Вы можете экспериментировать с этими эффектами, используя, например, инструмент разработчика FirefoxYou  <a href="https://wiki.developer.mozilla.org/en-US/docs/Tools/Style_Editor">редактор стилей</a>; смотрим <a href="https://wiki.developer.mozilla.org/en-US/docs/Tools/Page_Inspector/How_to/Edit_CSS_filters">Редактирование с CSS фильтрами</a> о подробностях выполнения.</p>
+
+<h2 id="Использование_определенных_устройств">Использование определенных устройств</h2>
+
+<p>При необходимости вы можете ограничить набор разрешенных источников видео, определенным устройством или набором устройств. Для этого нужно вызвать метод {{domxref("navigator.mediaDevices.enumerateDevices()")}}. Когда промис разрешиться массивом объектов {{domxref("MediaDeviceInfo")}} , описывающих доступные устройства , выберите те, которым хотите разрешить доступ и укажите соответствующий идентификатор устройства {{domxref("MediaTrackConstraints.deviceId", "deviceId")}} или несколько <code>deviceId</code> в объекте  {{domxref("MediaTrackConstraints")}} , переданном в  {{domxref("MediaDevices.getUserMedia", "getUserMedia()")}}.</p>
+
+<h2 id="Смотри_так_же">Смотри так же</h2>
+
+<ul>
+ <li><a href="https://mdn-samples.mozilla.org/s/webrtc-capturestill">Пробуем пример</a></li>
+ <li><a href="https://github.com/mdn/samples-server/tree/master/s/webrtc-capturestill">Примеры на Github</a></li>
+ <li>{{domxref("Navigator.mediaDevices.getUserMedia()")}}</li>
+ <li>{{SectionOnPage("/en-US/docs/Web/API/Canvas_API/Tutorial/Using_images","Использование изображений")}}</li>
+ <li>{{domxref("CanvasRenderingContext2D.drawImage()")}}</li>
+</ul>