WebRTC从摄像头获取图片传入canvas(Webrtc gets pictures from the camera and sends them to canvas)

WebRTC从摄像头获取图片传入canvas

前面我们已经能够利用WebRTC的功能,通过浏览器打开摄像头,并把预览的图像显示在video元素中。
接下来我们尝试从视频中截取某一帧,显示在界面上。

html

先准备一下界面,摆上控件。下面是关键部分的代码。

<video playsinline autoplay></video>
<button id="showVideo">打开摄像头</button>
<button id="takeSnapshot">截取</button>
<button id="clearList">清除记录</button>
<canvas id="mainCanvas"></canvas>
<div id="list" style="display: grid; grid-template-columns: repeat(auto-fill, 100px);
    column-gap: 20px; row-gap: 20px;"></div>
  • video 用来预览视频
  • 3个button,分别拿来打开摄像头,截取图片和清除记录
  • canvas 用来显示截取的图片
  • 下面的div是拿来存放多个截取图片记录的。给它指定了grid,显示多个图片时候比较好看一些

照例,需要引入

adapter-latest.js
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

js

准备实现功能。

打开摄像头并预览

和之前的打开摄像头类似,还是要用到方法。拿到视频流后交给video去播放。

getUserMedia
const video = document.querySelector('video');
const constraints = {
  audio: false,
  video: true
};
// ....

function openCamera(e) {
  navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(onError);
}

function gotStream(stream) {
  window.stream = stream;
  video.srcObject = stream;
}

function onError(error) {
  console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}

截取图片

拿到界面中的canvas,先预定一个尺寸(不预定也行)。

const mCanvas = window.canvas = document.querySelector('#mainCanvas');
mCanvas.width = 480;
mCanvas.height = 360;

// 开始截取
  mCanvas.width = video.videoWidth;
  mCanvas.height = video.videoHeight;
  mCanvas.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height);

发起截取后,使用获取到CanvasRenderingContext2D对象。然后调用它的方法。
把video中的视频帧绘制进去。

getContext
drawImage

除了绘制这一个canvas,我们可以在每次发起(点击按钮)的时候创建新的canvas,把它们像相册一样展示出来。

const list = document.querySelector('#list'); // 拿来存放多个元素

  // 新增1张
  var divItem = document.createElement("div");
  divItem.style.display = "block";
  divItem.width = 100;
  divItem.height = divItem.width * video.videoHeight / video.videoWidth; // 计算一下比例
  divItem.style.width = divItem.width + "px";
  divItem.style.height = divItem.height + "px";
  console.log("div item size: ", divItem.width, divItem.height);

  var c1 = document.createElement("canvas");
  c1.width = divItem.width;
  c1.height = divItem.height;
  c1.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height, 0, 0, c1.width, c1.height);

  divItem.appendChild(c1);
  list.appendChild(divItem);

子项的存放方式是div包裹canvas。先用创建。
按照视频的宽高,计算调整的大小,并设置style。

document.createElement("div")
divItem
divItem

创建,它的宽高设置为前面的宽高。然后把图片绘制进去。
时,前面传入的是视频(源)的范围,后面的4个参数是自己的绘制范围。
这样一个子项就生成完毕了。添加到我们准备好的列表(div)中。

document.createElement("canvas")
c1
divItem
drawImage

清除记录

清除div()里的子项。用一个循环获取并移除子项。

list
var child = list.lastElementChild;
while (child) {
    list.removeChild(child);
    child = list.lastElementChild;
}

小结

打开摄像头,显示视频。把视频绘制到canvas上。创建多个canvas,做成历史记录的效果。
主要利用的还是canvas的绘制方法。绘制的时候注意传入的参数,能够指定绘制的边界。
也就是说只绘制视频大小中的一部分也是可行的。

示例中用到的关键方法

  • getUserMedia
  • getContext
  • drawImage
  • createElement

预览

简易的预览链接

————————

WebRTC从摄像头获取图片传入canvas

Previously, we have been able to use the function of webrtc to open the camera through the browser and display the preview image in the video element.
Next, we try to capture a frame from the video and display it on the interface.

html

First prepare the interface and place the controls. The following is the key part of the code.

<video playsinline autoplay></video>
<button id="showVideo">打开摄像头</button>
<button id="takeSnapshot">截取</button>
<button id="clearList">清除记录</button>
<canvas id="mainCanvas"></canvas>
<div id="list" style="display: grid; grid-template-columns: repeat(auto-fill, 100px);
    column-gap: 20px; row-gap: 20px;"></div>
  • Video is used to preview the video
  • Three buttons are used to open the camera, intercept pictures and clear records respectively
  • Canvas is used to display the captured pictures
  • The following div is used to store multiple intercepted image records. Grid is assigned to it. It looks better when displaying multiple pictures

As usual, you need to introduce

adapter-latest.js
<script src="https://webrtc.github.io/adapter/adapter-latest.js"></script>

js

Prepare to implement the function.

Open camera and Preview

Similar to the previous method of opening the camera, it still needs to use the method. Give the video stream to < strong > Video < / strong > to play.

getUserMedia
const video = document.querySelector('video');
const constraints = {
  audio: false,
  video: true
};
// ....

function openCamera(e) {
  navigator.mediaDevices.getUserMedia(constraints).then(gotStream).catch(onError);
}

function gotStream(stream) {
  window.stream = stream;
  video.srcObject = stream;
}

function onError(error) {
  console.log('navigator.MediaDevices.getUserMedia error: ', error.message, error.name);
}

Capture picture

Get the canvas in the interface and book a size first (no reservation is OK).

const mCanvas = window.canvas = document.querySelector('#mainCanvas');
mCanvas.width = 480;
mCanvas.height = 360;

// 开始截取
  mCanvas.width = video.videoWidth;
  mCanvas.height = video.videoHeight;
  mCanvas.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height);

After the interception is initiated, the < strong > canvas renderingcontext2d < / strong > object is obtained by using. And then call its method.
Draw the video frames in the video.

getContext
drawImage

In addition to drawing this canvas, we can create a new canvas every time we launch (click the button) and display them like an album.

const list = document.querySelector('#list'); // 拿来存放多个元素

  // 新增1张
  var divItem = document.createElement("div");
  divItem.style.display = "block";
  divItem.width = 100;
  divItem.height = divItem.width * video.videoHeight / video.videoWidth; // 计算一下比例
  divItem.style.width = divItem.width + "px";
  divItem.style.height = divItem.height + "px";
  console.log("div item size: ", divItem.width, divItem.height);

  var c1 = document.createElement("canvas");
  c1.width = divItem.width;
  c1.height = divItem.height;
  c1.getContext('2d').drawImage(video, 0, 0, mCanvas.width, mCanvas.height, 0, 0, c1.width, c1.height);

  divItem.appendChild(c1);
  list.appendChild(divItem);

The storage method of sub items is div package canvas. Create with.
Calculate the adjusted size according to the width and height of the video, and set the style.

document.createElement("div")
divItem
divItem

Created, its width and height are set to the width and height of the front. Then draw the picture in.
When, the front input is the range of the video (source), and the last four parameters are their own drawing range.
So a child item is generated. Add to our prepared list (DIV).

document.createElement("canvas")
c1
divItem
drawImage

Clear record

Clear the children in div(). Get and remove children in a loop.

list
var child = list.lastElementChild;
while (child) {
    list.removeChild(child);
    child = list.lastElementChild;
}

Summary

Turn on the camera and display the video. Draw the video on canvas. Create multiple canvases to make the effect of history.
It mainly uses the drawing method of canvas. When drawing, pay attention to the passed parameters, which can specify the drawing boundary.
In other words, it is also feasible to draw only a part of the video size.

Key methods used in the example

  • getUserMedia
  • getContext
  • drawImage
  • createElement

preview

Easy preview link