Webカメラの映像をcanvasに表示させる

Webカメラの映像を解析(?)することがあったので、その工程をざっくりとまとめてみる。

内容をいっきに書き出すと長くなる予感がするので、今回はタイトルの通り「Webカメラの映像をcanvasに表示させる」まで。

次回は[「canvasに表示されている映像（画像）の色の判別する」](https://qiita.com/chelcat3/items/03419142aea295e94c69)。

日本語、英語ともに語彙力が乏しいので、優しく見守ってくれると嬉しい…。


## やること
- Webカメラの映像をvideo要素に表示させる。
- video要素に表示されている映像をcanvasに表示させる。


## Webカメラの映像をvideo要素に表示させる

htmlにvideoタグを直書きしてもよいが、個人的な趣味嗜好でjsで管理する。

```html:html
<div id="videoPreview">
  <p>video preview</p>
</div>
```

```javascript:javascript
const cameraSize = { w: 360, h: 240 };
const resolution = { w: 1080, h: 720 };
let video;
let media;

// video要素をつくる
video          = document.createElement('video');
video.id       = 'video';
video.width    = cameraSize.w;
video.height   = cameraSize.h;
video.autoplay = true;
document.getElementById('videoPreview').appendChild(video);

// video要素にWebカメラの映像を表示させる
media = navigator.mediaDevices.getUserMedia({
  audio: false,
  video: {
    width: { ideal: resolution.w },
    height: { ideal: resolution.h }
  }
}).then(function(stream) {
  video.srcObject = stream;
});
```

video要素は`autoplay`を有効にしておくか、もしくは`play()メソッド`で再生させる。

`getUserMedia()メソッド`はカメラやマイクなどにアクセスするメソッド。
今回、音声は必要ないので`audio: false`で切ってある。
カメラの解像度はその時々に応じて、良き感じに…。

そしてカメラのデータ(stream)をvideo要素の`srcObject`に代入することで表示される。

とりあえずこれでvideo要素にWebカメラの映像が表示される。


## video要素に表示されている映像をcanvasに表示させる

上記のvideo要素同様、htmlにcanvasタグを直書きしてもよいが、個人的な趣味嗜好でjsで（省略）

```html:html
<div id="videoPreview">
  <p>video preview</p>
</div>

<div id="canvasPreview">
  <p>canvas preview</p>
</div>
```

```javascript:javascript
const cameraSize = { w: 360, h: 240 };
const canvasSize = { w: 360, h: 240 };
const resolution = { w: 1080, h: 720 };
let video;
let media;
let canvas;
let canvasCtx;

// video要素をつくる
video          = document.createElement('video');
video.id       = 'video';
video.width    = cameraSize.w;
video.height   = cameraSize.h;
video.autoplay = true;
document.getElementById('videoPreview').appendChild(video);

// video要素にWebカメラの映像を表示させる
media = navigator.mediaDevices.getUserMedia({
  audio: false,
  video: {
    width: { ideal: resolution.w },
    height: { ideal: resolution.h }
  }
}).then(function(stream) {
  video.srcObject = stream;
});

// canvas要素をつくる
canvas        = document.createElement('canvas');
canvas.id     = 'canvas';
canvas.width  = canvasSize.w;
canvas.height = canvasSize.h;
document.getElementById('canvasPreview').appendChild(canvas);

// コンテキストを取得する
canvasCtx = canvas.getContext('2d');

// video要素の映像をcanvasに描画する
_canvasUpdate();

function _canvasUpdate() {
  canvasCtx.drawImage(video, 0, 0, canvas.width, canvas.height);
  requestAnimationFrame(_canvasUpdate);
};
```

canvas要素はあくまで描画領域であり描画する機能はお持ちでないので、`getContext()メソッド`で描画するためのコンテキストを取得する。
今回描画するのはビデオの映像なので、引数は '2d' 。
描画するときはこのコンテキストさんにお願いすればよい。

ここではコンテキストさんに`drawImage()メソッド`で
**video要素を、canvasの(0, 0)の位置に、canvas.width、canvas.heightの解像度で貼り付け**てくださいとお願いしている。

`drawImage()メソッド`は、img要素やvideo要素などをまるっと描画するメソッド。
このメソッドを呼び出したとき、表示されている画像を描画するような感じ。
よって、映像の場合はコマ送りをする必要があるため、`requestAnimationFrame()メソッド`でループさせている。

![qiita_190925.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/316493/b9d0b895-5d2e-1be3-a5bf-cacdf7b61e90.jpeg)


## まとめ
はやく語彙力のあるゴリゴリのエンジニアになりたい。


## 参考URL
https://developer.mozilla.org/ja/docs/Web/API/MediaDevices/getUserMedia
https://developer.mozilla.org/ja/docs/Web/API/Media_Streams_API