HTML5のWebRTCでPCに接続されたカメラ映像をウェブブラウザー上に表示してコマ画像を保存したい

#PCに接続されたカメラ映像をウェブブラウザー上に表示する

【目的】
PCに接続されたカメラの映像を分析するシステムを開発する。
HTML5やら、javascriptやらを使ってシンプルに映像取得、
静止画と保存したい。

【技術】
開発環境はWindows10です。映像は家電量販店で安く買える
USBカメラをUSB接続して使います。USBカメラからの映像を
ウェブブラウザー上に表示して、静止画としてダウンロード
保存できることの確認までやっていきます。今回はウェブサーバー
を立ち上げませんが、サーバーにソースを置く場合は、
ブラウザのセキュリティーポリシーに従ってURLを指定
しないと動作しません。（今回は気にする必要ありません）


## システムの実装
実装は、HTML5でWebRCT（Web Real-Time Communication）を使います。
基本的なjavascript言語の知識も必要です。

※  MediaDevices.getUserMedia() の使い方は下記を参照。
https://developer.mozilla.org/ja/docs/Web/API/Navigator/getUserMedia


```
<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>getUserMedia-Demo</title>
</head>
<body>

<!-- カメラ映像が描画されます。 -->
<video id="video_area" style="background-color: #000" autoplay></video>

<!-- 押下するとカメラ映像描画を開始します。 -->
<button id="start_btn">映像表示開始</button>

</body>
<script>

	// getUserMedia が使えないときは、『getUserMedia()が使えないブラウザだよ』と言ってね。
	if (typeof navigator.mediaDevices.getUserMedia !== 'function') {
		const err = new Error('getUserMedia()が使えないブラウザだよ');
		alert(`${err.name} ${err.message}`);
		throw err;
	}

	// 操作する画面エレメント変数定義します。
	const $start = document.getElementById('start_btn');   // スタートボタン
	const $video = document.getElementById('video_area');  // 映像表示エリア

	// 「スタートボタン」を押下で、getUserMedia を使って映像を「映像表示エリア」に表示するよ。
	$start.addEventListener('click', () => {
		navigator.mediaDevices.getUserMedia({ video: true, audio: false })
		.then(stream => $video.srcObject = stream)
		.catch(err => alert(`${err.name} ${err.message}`));
	}, false);
	
</script>

</html>

```
上記のHTMLを『camdemo.html』の名称でUTF-8エンコードで保存します。
USBカメラが接続されているPCで、Chromeブラウザーで直接開いてみてください。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/8f0bf489-a968-4a6e-03b8-0a9d887ecf58.png)

『映像表示開始』ボタンを押下します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/11f02dbc-8cc9-29da-ca6d-5ae0f88b313f.png)

カメラを使用するので、「許可」します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/e700ee3b-cf50-ea7f-c9c9-89b0ccade1d2.png)

はい、映像が表示されました。
映像は静止画ではなく、動画映像として、表示されます。

## 映像から静止画（コマ画像）をcanvasエリアに表示します。

映像のコマ画像を、画面上の別のエリアに静止画として表示するコードを追加していきます。

実装はシンプルです。
１．「静止画キャプチャ」ボタンを追加します。
２．キャプチャーした静止画を表示するエリアを追加します。
３．（１．）のボタン押下で（２．）のエリアに画像を表示するコードを追加します。

```

<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width">
  <title>getUserMedia-Demo</title>
</head>
<body>

	<!-- カメラ映像が描画されます。 -->
	<video id="video_area" style="background-color: #000" autoplay></video>

	<!-- 押下するとカメラ映像描画を開始します。 -->
	<button id="start_btn">映像表示開始</button>

	<!-- 押下するとカメラ映像から静止画をキャプチャします。 -->
	<button onclick="copyFrame()">静止画取得</button>

	<!-- キャプチャした静止画が描画されます。 -->
	<canvas id="capture_image"></canvas>

</body>
<script>

	// getUserMedia が使えないときは、『getUserMedia()が利用できないブラウザです！』と言ってね。
	if (typeof navigator.mediaDevices.getUserMedia !== 'function') {
		const err = new Error('getUserMedia()が利用できないブラウザです！');
		alert(`${err.name} ${err.message}`);
		throw err;
	}

	// 操作する画面エレメント変数定義します。
	const $start = document.getElementById('start_btn');   // スタートボタン
	const $video = document.getElementById('video_area');  // 映像表示エリア

	// 「スタートボタン」を押下したら、getUserMedia を使って映像を「映像表示エリア」に表示してね。
	$start.addEventListener('click', () => {
		navigator.mediaDevices.getUserMedia({ video: true, audio: false })
		.then(stream => $video.srcObject = stream)
		.catch(err => alert(`${err.name} ${err.message}`));
	}, false);
	
	
	// 「静止画取得」ボタンが押されたら「<canvas id="capture_image">」に映像のコマ画像を表示します。
	function copyFrame() {

	    var canvas_capture_image = document.getElementById('capture_image');
	    var cci = canvas_capture_image.getContext('2d');
	    var va = document.getElementById('video_area');
	    
	    canvas_capture_image.width  = va.videoWidth;
	    canvas_capture_image.height = va.videoHeight;
		cci.drawImage(va, 0, 0);  // canvasに『「静止画取得」ボタン』押下時点の画像を描画。
	}
	
	
</script>

</html>

```

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/3f08e326-9e4f-468d-14f0-368fb381483b.png)

「静止画取得」ボタンを押下します。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/191aa617-3750-6f53-f06a-3d8669928c91.png)

「静止画取得」ボタンを押下した瞬間の映像が複写されました。
静止画なので、映像が変化しても一度キャプチャした映像は変わりません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/397f97d5-b878-cfda-a0aa-08b69f779ac3.png)

もう一度「静止画取得」ボタンを押下すれば、静止画も更新されます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/1ec7920d-e165-3082-2a12-1e914c438088.png)

静止画側の画像の上で、マウス右クリックで「名前を付けて画像を保存」することができます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/3d5fdb5d-e0bf-5ffa-3ac2-2a9cc0b3cb1f.png)

Windows標準のペイントで開いてみました。こんな感じです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/303278/d57402ea-4db2-0a4f-aa89-362460ad8332.png)

また、『toDataURL() メソッド』を使って画像を所定の名称でダウンロード保存させることもできます。

それはまた次回。

以上です。