[HTML5] カメラをJSで操作し写真を撮影する

  • このエントリーをはてなブックマークに追加
  • LINEで送る
この記事は 2019年6月18日 に書かれたものです

HTML5ではPCやスマホのデバイスの機能をJavaScriptから直接利用することができるようになりました。今回はカメラを操作し、デジカメのような要領で静止画を撮影する簡単なサンプルを作ってみたいと思います。

カメラの映像が向かって左側に写り続け、良いタイミングで下にある「シャッター」ボタンをクリックすると、右側に撮影した静止画が表示されます。ボタンをクリックするとシャッター音も再生されます。

- Sponsored Link -

サンプル

実行例

以下のページから実際にサンプルを実行できます。

初回のアクセス時にWebブラウザから、このサイトにカメラの操作を許可して良いか聞かれますので「許可」ボタンをクリックしてください。「ブロック」ボタンを押すと設定を変更するのにメニューの少し深いところに潜る必要がありますのでご注意を。

ソースコード

<!DOCTYPE html>
<html>
<head>
  <meta charset="UTF-8">
  <title>Camera Test</title>
  <style>
  canvas, video{
    border: 1px solid gray;
  }
  </style>
</head>
<body>

<h1>HTML5カメラ</h1>

<video id="camera" width="300" height="200"></video>
<canvas id="picture" width="300" height="200"></canvas>
<form>
  <button type="button" id="shutter">シャッター</button>
</form>

<audio id="se" preload="auto">
  <source src="camera-shutter1.mp3" type="audio/mp3">
</audio>

<script>
window.onload = () => {
  const video  = document.querySelector("#camera");
  const canvas = document.querySelector("#picture");
  const se     = document.querySelector('#se');

  /** カメラ設定 */
  const constraints = {
    audio: false,
    video: {
      width: 300,
      height: 200,
      facingMode: "user"   // フロントカメラを利用する
      // facingMode: { exact: "environment" }  // リアカメラを利用する場合
    }
  };

  /**
   * カメラを<video>と同期
   */
  navigator.mediaDevices.getUserMedia(constraints)
  .then( (stream) => {
    video.srcObject = stream;
    video.onloadedmetadata = (e) => {
      video.play();
    };
  })
  .catch( (err) => {
    console.log(err.name + ": " + err.message);
  });

  /**
   * シャッターボタン
   */
   document.querySelector("#shutter").addEventListener("click", () => {
    const ctx = canvas.getContext("2d");

    // 演出的な目的で一度映像を止めてSEを再生する
    video.pause();  // 映像を停止
    se.play();      // シャッター音
    setTimeout( () => {
      video.play();    // 0.5秒後にカメラ再開
    }, 500);

    // canvasに画像を貼り付ける
    ctx.drawImage(video, 0, 0, canvas.width, canvas.height);
  });
};
</script>
</body>
</html>

解説

大まかな原理

navigator.mediaDevices.getUserMedia()が、引数として渡した連想配列の内容に従ってカメラからの映像をストリームとして持ってきてくれます。このストリームを<video>要素にそのまま流し込んでいます。「シャッター」ボタンをクリックすると、押した瞬間の<video>の内容を画像として取り出し、<canvas>にそのまま貼り付けているだけです。

サンプルではボタンをクリックすると一瞬止まりますが、その方がデジカメ感があるため演出として付けているだけで、不要であればvideo.pause();からsetTimeout()あたりのコードを削除すれば処理その物は一瞬で終わります。

カメラが存在しない場合は?

navigator.mediaDevices.getUserMedia()が例外を発生、.catch()で捕捉されます。
ここではフロントカメラを指定していますが、もしリアカメラを指定しリアカメラがない機器の場合は同様にエラーが返される可能性があります。

オプション

特に指定しない

単に映像と音に対し利用するかどうかBooleanで指定するだけです。

  const constraints = {
    audio: false,
    video: true
  };

解像度の最小値と最大値

サンプルのようにwidth,heightの値を固定することもできますが、minで最小値、maxで最大値を指定することもできます。

  const constraints = {
    audio: false,
    video: {
       width: { min: 800, max: 1920 },
      height: { min: 600, max: 1080 }
    }
  };

またidealという指定もできます。直訳すると「理想」という意味ですが、idealで指定した解像度になるべく近い映像を返すよう努力してくれます。

  const constraints = {
    audio: false,
    video: {
       width: { min: 800, ideal: 1280, max: 1920 },
      height: { min: 600, ideal:  720, max: 1080 }
    }
  };

素材

SE(シャッター音)
効果音ラボ https://soundeffect-lab.info/

参考ページ

コメント

コメント欄は休止中です。お問い合わせはこちらからどうぞ。ご質問はTwitterにリプを投げてください。

このブログを応援する

お寄せいただいたお気持ちは全額サーバ代や次の記事を執筆するための原資として活用させていただいております。この記事が参考になった場合などぜひご検討ください。

PayPal(ペイパル)
PayPalで300円支払う
※金額は任意で変更できます。
※100円でも泣いて喜びますw
※住所の入力欄が現れた場合は「no needed」を選択ください
これまでのご協力者さま
- Sponsored Link -

旧コメント欄(表示のみ)

※こちらのコメント欄は以前稼働していたものです。現在は新たに書き込むことはできません。ご感想やご質問は記事の下にあるコメント欄をご利用ください。
  1. 丸尾スエ より:

    デスクトップのchromeでは動いたんですが、iPhoneのchromeでは動かないんですよね、何か情報ご存知ありませんか

    1. 勝部 麻季人 より:

      丸尾スエさん
      ブログをご覧いただきありがとうございます。iOS版のChromeはWKWebView(要はSafariの機能限定版です)という機能を利用しているのですが、こいつがgetUserMedia()に対応していないため利用できないようです。iOSは独自の仕組みでWebページを表示することを禁止していますので、Appleが対応するまでは難しそうですね。