みかづきブログ その3

3ヶ月つづけてみました。

Electronをつかってウェブカメラで写真を撮るデスクトップアプリをつくろう。

kimizuka.hatenablog.com
kimizuka.hatenablog.com
kimizuka.hatenablog.com

前回 はカメラを起動するところまでのアプリをつくったので、
今回は実際に写真をとってローカルに保存するところまでつくってみましょう。

前回 までのコードを編集していきます。


package.json

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "data-uri-to-buffer": "0.0.4",
    "electron-prebuilt": "^1.2.1",
    "fs": "0.0.2"
  }
}

base64をファイルに変換するために data-uri-to-buffer を、
ファイルを保存するために fs を追加しました。


main.js

"use strict";

var electron      = require("electron"),
    app           = electron.app,
    BrowserWindow = electron.BrowserWindow,
    mainWindow;

app.on("ready", function() {
  mainWindow = new BrowserWindow({
    width  : 640,
    height : 500
  });

  mainWindow.loadURL("file://" + __dirname + "/index.html");

  mainWindow.on("closed", function() {
    mainWindow = null;
  });
});

変更なしです。


index.html

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8">
    <link rel="stylesheet" href="index.css">
    <title>Camera</title>
  </head>
  <body>
    <video id="video"></video>
    <script src="index.js"></script>
  </body>
</html>

基本的には変更無しなんですが、前回の心残りであったCSSのファイル名を変更しました。
main.cssではなくindex.cssを読み込むようになっています。


index.css

* {
  margin: 0; padding: 0;
}

body {
  background: #000;
  overflow: hidden;
}

#video {
  display: block;
  position: absolute;
  top: 0; bottom: 0;
  left: 0; right: 0;
  margin: auto;
  width: 640px; height: 480px;
}

ファイル名以外変更なしです。


index.js

"use strict";

var dataUriToBuffer = require("data-uri-to-buffer"), // モジュールの読み込み
    fs              = require("fs"), // モジュールの読み込み
    video           = document.getElementById("video"),
    canvas          = document.createElement("canvas"),
    ctx             = canvas.getContext("2d"),
    imageFilePath   = "/Users/#{ユーザー名}/photo"; // #{ユーザー名}の部分を自分のユーザー名に変更する必要あり

navigator.webkitGetUserMedia({video: true, audio: false}, _handleSuccess, _handleError);

document.addEventListener("keypress", function(evt) { // キーイベント
  if (evt.charCode === 32) { // スペースキーを押した時の処理
      canvas.width  = 640;
      canvas.height = 480;
      ctx.drawImage(video, 0, 0);

      fs.writeFile(imageFilePath + Date.now() + ".png", dataUriToBuffer(canvas.toDataURL()), function(err) {
        if (err) {
          // 失敗
          console.log(err);
        } else {
          // 成功
        }
      });
  }
}, false);

function _handleSuccess(localMediaStream) {
  video.style.display = "block";
  video.src = window.URL.createObjectURL(localMediaStream);
  video.play();
}

function _handleError() {
  alert("ERROR: カメラを起動できませんでした。");
}

変更点が多いのでコメントとして記載しました。
大雑把にまとめると、

  1. モジュールの読み込み
  2. スペースキーを押した時の処理(Canvasへの書き込み・base64化・ファイル化・保存)

を追加しています。

ファイルを保存する際のパスを /User/#{ユーザー名} 以下にしないとパーミッションエラーになり、
~/ を使って指定してもエラーになりました。後者は謎です。書き方が良くないのかもしれません。


今回は以上です。
次回は遠隔でシャッターを切れるように編集していきたいと思います。