読者です 読者をやめる 読者になる 読者になる

森川敬一 CTO ブログ

unimediaでCTOやってます森川敬一です。エンジニアブログ。IoT、ウエアブルとか書いていきます。

RaspberryPi B+でカメラモジュール使ってnode.jsとsocket.ioでストリーミング配信してみる

RaspberryPi B+でカメラモジュール使ってnode.jsとsocket.ioでストリーミング配信してみます。

純正カメラをつなげました。

f:id:m-kei1:20150220113541j:plainf:id:m-kei1:20150220113556j:plain

ついでにネットワークがつながってるので、シリアルログインが不要のためmicroUSBケーブルで接続してます。

カメラの有効化を行います
# sudo raspi-config
f:id:m-kei1:20150220113738p:plain
f:id:m-kei1:20150220113748p:plain

下記を参考にさせて頂きます

Raspberry Pi, Camera and Node.js - Live Streaming with Websockets #IoT | The Jackal of Javascript



liveStreamingフォルダを作って、expressをsocket.io付きでinitします。

http://thejackalofjavascript.com/rpi-live-streaming/


pi@raspberrypi ~ $ cd httpd/
pi@raspberrypi ~/httpd $ ls
sample
pi@raspberrypi ~/httpd $ mkdir liveStreaming && cd liveStreaming
pi@raspberrypi ~/httpd/liveStreaming $ ls
pi@raspberrypi ~/httpd/liveStreaming $ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sane defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg> --save` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
name: (liveStreaming) liveStreaming
version: (0.0.0)
description:
entry point: (index.js)
test command:
git repository:
keywords:
author:
license: (ISC)
About to write to /home/pi/httpd/liveStreaming/package.json:

{
  "name": "liveStreaming",
  "version": "0.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC"
}


Is this ok? (yes)

pi@raspberrypi ~/httpd/liveStreaming $ npm install express socket.io --save
npm WARN package.json liveStreaming@0.0.0 No description
npm WARN package.json liveStreaming@0.0.0 No repository field.
npm WARN package.json liveStreaming@0.0.0 No README data
npm http GET https://registry.npmjs.org/socket.io
npm http GET https://registry.npmjs.org/express
npm http 200 https://registry.npmjs.org/socket.io
npm http 200 https://registry.npmjs.org/express
npm http GET https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz
npm http 200 https://registry.npmjs.org/socket.io/-/socket.io-1.3.4.tgz
npm http GET https://registry.npmjs.org/engine.io
npm http GET https://registry.npmjs.org/socket.io-parser
npm http GET https://registry.npmjs.org/socket.io-client
npm http GET https://registry.npmjs.org/socket.io-adapter
npm http GET https://registry.npmjs.org/has-binary-data
npm http GET https://registry.npmjs.org/debug
npm http 200 https://registry.npmjs.org/has-binary-data
npm http 200 https://registry.npmjs.org/debug
npm http 200 https://registry.npmjs.org/socket.io-adapter
npm http 200 https://registry.npmjs.org/socket.io-parser
npm http 200 https://registry.npmjs.org/socket.io-client
npm http GET https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz
npm http GET https://registry.npmjs.org/debug/-/debug-2.1.0.tgz
npm http GET https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz
npm http GET https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz
npm http 200 https://registry.npmjs.org/has-binary-data/-/has-binary-data-0.1.3.tgz
npm http 200 https://registry.npmjs.org/engine.io
npm http 200 https://registry.npmjs.org/socket.io-adapter/-/socket.io-adapter-0.3.1.tgz
npm http 200 https://registry.npmjs.org/debug/-/debug-2.1.0.tgz
npm http GET https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz
npm http 200 https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.3.tgz
npm http 200 https://registry.npmjs.org/socket.io-client/-/socket.io-client-1.3.4.tgz
npm http GET https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz
npm http 200 https://registry.npmjs.org/engine.io/-/engine.io-1.5.1.tgz
npm http GET https://registry.npmjs.org/methods
npm http GET https://registry.npmjs.org/fresh
npm http GET https://registry.npmjs.org/media-typer
npm http GET https://registry.npmjs.org/on-finished
npm http GET https://registry.npmjs.org/parseurl
npm http GET https://registry.npmjs.org/path-to-regexp
npm http GET https://registry.npmjs.org/proxy-addr
npm http GET https://registry.npmjs.org/qs
npm http GET https://registry.npmjs.org/range-parser
npm http GET https://registry.npmjs.org/send
npm http GET https://registry.npmjs.org/serve-static
npm http GET https://registry.npmjs.org/type-is
npm http GET https://registry.npmjs.org/vary
npm http GET https://registry.npmjs.org/cookie
npm http GET https://registry.npmjs.org/merge-descriptors
npm http GET https://registry.npmjs.org/utils-merge
npm http GET https://registry.npmjs.org/accepts
npm http GET https://registry.npmjs.org/content-disposition
npm http GET https://registry.npmjs.org/cookie-signature
npm http GET https://registry.npmjs.org/depd
npm http GET https://registry.npmjs.org/escape-html
npm http GET https://registry.npmjs.org/etag
npm http GET https://registry.npmjs.org/finalhandler
npm http 304 https://registry.npmjs.org/methods
npm http 304 https://registry.npmjs.org/on-finished
npm http 304 https://registry.npmjs.org/fresh
npm http 304 https://registry.npmjs.org/parseurl
npm http 304 https://registry.npmjs.org/path-to-regexp
npm http 304 https://registry.npmjs.org/range-parser
npm http 200 https://registry.npmjs.org/proxy-addr
npm http 200 https://registry.npmjs.org/qs
npm http 304 https://registry.npmjs.org/vary
npm http 304 https://registry.npmjs.org/media-typer
npm http 304 https://registry.npmjs.org/cookie
npm http 200 https://registry.npmjs.org/serve-static
npm http 200 https://registry.npmjs.org/send
npm http GET https://registry.npmjs.org/qs/-/qs-2.3.3.tgz
npm http 304 https://registry.npmjs.org/utils-merge
npm http 304 https://registry.npmjs.org/merge-descriptors
npm http 200 https://registry.npmjs.org/cookie-signature
npm http 304 https://registry.npmjs.org/content-disposition
npm http 200 https://registry.npmjs.org/accepts
npm http 200 https://registry.npmjs.org/qs/-/qs-2.3.3.tgz
npm http 200 https://registry.npmjs.org/type-is
npm http 304 https://registry.npmjs.org/depd
npm http 304 https://registry.npmjs.org/escape-html
npm http 304 https://registry.npmjs.org/etag
npm http GET https://registry.npmjs.org/send/-/send-0.11.1.tgz
npm http 304 https://registry.npmjs.org/finalhandler
npm http GET https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz
npm http 200 https://registry.npmjs.org/send/-/send-0.11.1.tgz
npm http 200 https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.5.tgz
npm http GET https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz
npm http 200 https://registry.npmjs.org/accepts/-/accepts-1.2.4.tgz
npm http GET https://registry.npmjs.org/crc
npm http GET https://registry.npmjs.org/ee-first
npm http GET https://registry.npmjs.org/mime-types
npm http GET https://registry.npmjs.org/negotiator
npm http GET https://registry.npmjs.org/ipaddr.js
npm http GET https://registry.npmjs.org/forwarded
npm http 304 https://registry.npmjs.org/ee-first
npm http 304 https://registry.npmjs.org/crc
npm http 304 https://registry.npmjs.org/forwarded
npm http 304 https://registry.npmjs.org/mime-types
npm http 200 https://registry.npmjs.org/negotiator
npm http 304 https://registry.npmjs.org/ipaddr.js
npm http GET https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz
npm http GET https://registry.npmjs.org/object-keys
npm http 200 https://registry.npmjs.org/negotiator/-/negotiator-0.5.1.tgz
npm http GET https://registry.npmjs.org/debug
npm http GET https://registry.npmjs.org/socket.io-parser
npm http GET https://registry.npmjs.org/destroy
npm http GET https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/ms
npm http 200 https://registry.npmjs.org/object-keys
npm http 304 https://registry.npmjs.org/debug
npm http 304 https://registry.npmjs.org/socket.io-parser
npm http 304 https://registry.npmjs.org/destroy
npm http 304 https://registry.npmjs.org/ms
npm http 200 https://registry.npmjs.org/mime
npm http GET https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz
npm http GET https://registry.npmjs.org/debug/-/debug-1.0.2.tgz
npm http GET https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz
npm http GET https://registry.npmjs.org/mime/-/mime-1.2.11.tgz
npm http 200 https://registry.npmjs.org/object-keys/-/object-keys-1.0.1.tgz
npm http 200 https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-2.2.2.tgz
npm http 200 https://registry.npmjs.org/mime/-/mime-1.2.11.tgz
npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.2.tgz
npm http GET https://registry.npmjs.org/json3
npm http GET https://registry.npmjs.org/component-emitter
npm http GET https://registry.npmjs.org/isarray
npm http GET https://registry.npmjs.org/benchmark
npm http 200 https://registry.npmjs.org/isarray
npm http GET https://registry.npmjs.org/debug/-/debug-0.7.4.tgz
npm http 200 https://registry.npmjs.org/component-emitter
npm http GET https://registry.npmjs.org/mime-db
npm http 200 https://registry.npmjs.org/json3
npm http 200 https://registry.npmjs.org/benchmark
npm http 200 https://registry.npmjs.org/debug/-/debug-0.7.4.tgz
npm http 304 https://registry.npmjs.org/mime-db
npm http GET https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz
npm http GET https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz
npm http GET https://registry.npmjs.org/json3/-/json3-3.2.6.tgz
npm http GET https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz
npm http 200 https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz
npm http 200 https://registry.npmjs.org/component-emitter/-/component-emitter-1.1.2.tgz
npm http 200 https://registry.npmjs.org/json3/-/json3-3.2.6.tgz
npm http 200 https://registry.npmjs.org/benchmark/-/benchmark-1.0.0.tgz
npm http GET https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/engine.io-parser
npm http GET https://registry.npmjs.org/base64id
npm http GET https://registry.npmjs.org/debug
npm http 304 https://registry.npmjs.org/debug
npm http 200 https://registry.npmjs.org/engine.io-parser
npm http 200 https://registry.npmjs.org/ws
npm http 200 https://registry.npmjs.org/base64id
npm http GET https://registry.npmjs.org/debug/-/debug-1.0.3.tgz
npm http GET https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz
npm http GET https://registry.npmjs.org/ws/-/ws-0.5.0.tgz
npm http GET https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz
npm http 200 https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-1.2.1.tgz
npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.3.tgz
npm http 200 https://registry.npmjs.org/base64id/-/base64id-0.1.0.tgz
npm http 200 https://registry.npmjs.org/ws/-/ws-0.5.0.tgz
npm http GET https://registry.npmjs.org/ms
npm http 304 https://registry.npmjs.org/ms
npm http GET https://registry.npmjs.org/component-emitter
npm http GET https://registry.npmjs.org/isarray
npm http 304 https://registry.npmjs.org/isarray
npm http 304 https://registry.npmjs.org/component-emitter
npm http GET https://registry.npmjs.org/engine.io-client
npm http GET https://registry.npmjs.org/component-bind
npm http GET https://registry.npmjs.org/object-component
npm http GET https://registry.npmjs.org/has-binary
npm http GET https://registry.npmjs.org/indexof
npm http GET https://registry.npmjs.org/parseuri
npm http GET https://registry.npmjs.org/to-array
npm http GET https://registry.npmjs.org/backo2
npm http GET https://registry.npmjs.org/debug
npm http 200 https://registry.npmjs.org/object-component
npm http 200 https://registry.npmjs.org/component-bind
npm http 200 https://registry.npmjs.org/indexof
npm http 200 https://registry.npmjs.org/to-array
npm http 200 https://registry.npmjs.org/backo2
npm http 304 https://registry.npmjs.org/debug
npm http 200 https://registry.npmjs.org/has-binary
npm http 200 https://registry.npmjs.org/parseuri
npm http GET https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz
npm http GET https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz
npm http GET https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz
npm http 200 https://registry.npmjs.org/engine.io-client
npm http GET https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz
npm http GET https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz
npm http 200 https://registry.npmjs.org/indexof/-/indexof-0.0.1.tgz
npm http GET https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz
npm http 200 https://registry.npmjs.org/object-component/-/object-component-0.0.3.tgz
npm http 200 https://registry.npmjs.org/component-bind/-/component-bind-1.0.0.tgz
npm http GET https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz
npm http 200 https://registry.npmjs.org/to-array/-/to-array-0.1.3.tgz
npm http 200 https://registry.npmjs.org/has-binary/-/has-binary-0.1.6.tgz
npm http 200 https://registry.npmjs.org/backo2/-/backo2-1.0.2.tgz
npm http GET https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz
npm http 200 https://registry.npmjs.org/parseuri/-/parseuri-0.0.2.tgz
npm http 200 https://registry.npmjs.org/engine.io-client/-/engine.io-client-1.5.1.tgz
npm http GET https://registry.npmjs.org/ms
npm http 304 https://registry.npmjs.org/ms
npm http GET https://registry.npmjs.org/arraybuffer.slice
npm http GET https://registry.npmjs.org/after
npm http GET https://registry.npmjs.org/base64-arraybuffer
npm http GET https://registry.npmjs.org/blob
npm http GET https://registry.npmjs.org/utf8
npm http GET https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz
npm http 200 https://registry.npmjs.org/base64-arraybuffer
npm http 200 https://registry.npmjs.org/arraybuffer.slice
npm http 200 https://registry.npmjs.org/after
npm http 200 https://registry.npmjs.org/has-binary/-/has-binary-0.1.5.tgz
npm http GET https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz
npm http GET https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz
npm http 200 https://registry.npmjs.org/blob
npm http GET https://registry.npmjs.org/after/-/after-0.8.1.tgz
npm http 200 https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-0.1.2.tgz
npm http 200 https://registry.npmjs.org/arraybuffer.slice/-/arraybuffer.slice-0.0.6.tgz
npm http 200 https://registry.npmjs.org/after/-/after-0.8.1.tgz
npm http GET https://registry.npmjs.org/blob/-/blob-0.0.2.tgz
npm http 200 https://registry.npmjs.org/utf8
npm http 200 https://registry.npmjs.org/blob/-/blob-0.0.2.tgz
npm http GET https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz
npm http 200 https://registry.npmjs.org/utf8/-/utf8-2.0.0.tgz
npm http GET https://registry.npmjs.org/better-assert
npm http 200 https://registry.npmjs.org/better-assert
npm http GET https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz
npm http 200 https://registry.npmjs.org/better-assert/-/better-assert-1.0.2.tgz
npm http GET https://registry.npmjs.org/nan
npm http GET https://registry.npmjs.org/options
npm http GET https://registry.npmjs.org/ultron
npm http 200 https://registry.npmjs.org/options
npm http GET https://registry.npmjs.org/options/-/options-0.0.6.tgz
npm http 200 https://registry.npmjs.org/ultron
npm http GET https://registry.npmjs.org/isarray
npm http 200 https://registry.npmjs.org/nan
npm http 200 https://registry.npmjs.org/options/-/options-0.0.6.tgz
npm http 304 https://registry.npmjs.org/isarray
npm http GET https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz
npm http GET https://registry.npmjs.org/nan/-/nan-1.4.3.tgz
npm http 200 https://registry.npmjs.org/ultron/-/ultron-1.0.1.tgz
npm http 200 https://registry.npmjs.org/nan/-/nan-1.4.3.tgz
npm http GET https://registry.npmjs.org/callsite
npm http 200 https://registry.npmjs.org/callsite
npm http GET https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz
npm http 200 https://registry.npmjs.org/callsite/-/callsite-1.0.0.tgz
npm http GET https://registry.npmjs.org/parsejson
npm http GET https://registry.npmjs.org/parseqs
npm http GET https://registry.npmjs.org/component-inherit
npm http GET https://registry.npmjs.org/has-cors
npm http GET https://github.com/rase-/node-XMLHttpRequest/archive/a6b6f2.tar.gz
npm http GET https://registry.npmjs.org/ws
npm http GET https://registry.npmjs.org/engine.io-parser
npm http GET https://registry.npmjs.org/debug
npm http GET https://registry.npmjs.org/parseuri
npm http 200 https://registry.npmjs.org/has-cors
npm http 200 https://registry.npmjs.org/parseqs
npm http 304 https://registry.npmjs.org/engine.io-parser
npm http 200 https://registry.npmjs.org/parsejson
npm http 304 https://registry.npmjs.org/ws
npm http 200 https://registry.npmjs.org/component-inherit
npm http 304 https://registry.npmjs.org/debug
npm http 304 https://registry.npmjs.org/parseuri
npm http GET https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz
npm http GET https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz
npm http GET https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz
npm http GET https://registry.npmjs.org/ws/-/ws-0.4.31.tgz
npm http GET https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz
npm http GET https://registry.npmjs.org/debug/-/debug-1.0.4.tgz
npm http GET https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz
npm http 200 https://registry.npmjs.org/parseqs/-/parseqs-0.0.2.tgz
npm http 200 https://registry.npmjs.org/debug/-/debug-1.0.4.tgz
npm http 200 https://registry.npmjs.org/component-inherit/-/component-inherit-0.0.3.tgz
npm http 200 https://registry.npmjs.org/ws/-/ws-0.4.31.tgz
npm http 200 https://registry.npmjs.org/parsejson/-/parsejson-0.0.1.tgz
npm http 200 https://registry.npmjs.org/parseuri/-/parseuri-0.0.4.tgz
npm http 200 https://registry.npmjs.org/has-cors/-/has-cors-1.0.3.tgz
npm http 200 https://github.com/rase-/node-XMLHttpRequest/archive/a6b6f2.tar.gz
npm http GET https://registry.npmjs.org/isarray
npm http 200 https://registry.npmjs.org/nan/-/nan-0.3.2.tgz

> ws@0.4.31 install /home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws
> (node-gyp rebuild 2> builderror.log) || (exit 0)

make: Entering directory '/home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
  CXX(target) Release/obj.target/bufferutil/src/bufferutil.o
  SOLINK_MODULE(target) Release/obj.target/bufferutil.node
  SOLINK_MODULE(target) Release/obj.target/bufferutil.node: Finished
  COPY Release/bufferutil.node
  CXX(target) Release/obj.target/validation/src/validation.o
  SOLINK_MODULE(target) Release/obj.target/validation.node
  SOLINK_MODULE(target) Release/obj.target/validation.node: Finished
  COPY Release/validation.node
make: Leaving directory '/home/pi/httpd/liveStreaming/node_modules/socket.io/node_modules/socket.io-client/node_modules/engine.io-client/node_modules/ws/build'
express@4.11.2 node_modules/express
├── utils-merge@1.0.0
├── merge-descriptors@0.0.2
├── methods@1.1.1
├── fresh@0.2.4
├── cookie@0.1.2
├── escape-html@1.0.1
├── range-parser@1.0.2
├── cookie-signature@1.0.5
├── finalhandler@0.3.3
├── vary@1.0.0
├── media-typer@0.3.0
├── parseurl@1.3.0
├── serve-static@1.8.1
├── content-disposition@0.5.0
├── path-to-regexp@0.1.3
├── depd@1.0.0
├── on-finished@2.2.0 (ee-first@1.1.0)
├── qs@2.3.3
├── debug@2.1.1 (ms@0.6.2)
├── proxy-addr@1.0.6 (forwarded@0.1.0, ipaddr.js@0.1.8)
├── etag@1.5.1 (crc@3.2.1)
├── send@0.11.1 (destroy@1.0.3, ms@0.7.0, mime@1.2.11)
├── type-is@1.5.7 (mime-types@2.0.9)
└── accepts@1.2.4 (negotiator@0.5.1, mime-types@2.0.9)

socket.io@1.3.4 node_modules/socket.io
├── debug@2.1.0 (ms@0.6.2)
├── has-binary-data@0.1.3 (isarray@0.0.1)
├── socket.io-parser@2.2.3 (isarray@0.0.1, debug@0.7.4, component-emitter@1.1.2, benchmark@1.0.0, json3@3.2.6)
├── socket.io-adapter@0.3.1 (object-keys@1.0.1, debug@1.0.2, socket.io-parser@2.2.2)
├── engine.io@1.5.1 (base64id@0.1.0, debug@1.0.3, engine.io-parser@1.2.1, ws@0.5.0)
└── socket.io-client@1.3.4 (to-array@0.1.3, indexof@0.0.1, component-bind@1.0.0, debug@0.7.4, backo2@1.0.2, object-component@0.0.3, component-emitter@1.1.2, has-binary@0.1.6, parseuri@0.0.2, engine.io-client@1.5.1)


準備完了したら、
index.js(サーバー側)とindex.html(クライアント側)を作成します。

index.js

var express = require('express');
var app = express();
var http = require('http').Server(app);
var io = require('socket.io')(http);
var fs = require('fs');
var path = require('path');

var spawn = require('child_process').spawn;
var proc;

var dateformat = require("dateformat");

app.use('/', express.static(path.join(__dirname, 'stream')));

app.get('/', function(req, res) {
	res.sendFile(__dirname + '/index.html');
});

var sockets = {};

io.on('connection', function(socket) {
	sockets[socket.id] = socket;
	console.log("Total clients connected : ", Object.keys(sockets).length);

	socket.on('disconnect', function() {

		delete sockets[socket.id];
		// no more sockets, kill the stream
		if (Object.keys(sockets).length == 0) {
			app.set('watchingFile', false);
			if (proc) proc.kill();
			fs.unwatchFile('./stream/image_stream.jpg');
		}
	});
	socket.on('start-stream', function() {
		startStreaming(io);
	});
});

http.listen(3000, function() {
	console.log('listening on *:3000');
});

function stopStreaming() {

	if (Object.keys(sockets).length == 0) {
		app.set('watchingFile', false);
		if (proc) proc.kill();
		fs.unwatchFile('./stream/image_stream.jpg');
	}
}

function startStreaming(io) {
	if (app.get('watchingFile')) {
		io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")});
		return;
	}

	var args = ["-bm", "-w", "320", "-h", "240", "-o", __dirname + "/stream/image_stream.jpg", "-t", "999999999", "-tl", "500", "--nopreview"];
	proc = spawn('raspistill', args);
	console.log('Watching for changes...');
	app.set('watchingFile', true);

	fs.watchFile(__dirname+'/stream/image_stream.jpg', function(current, previous) {
		console.log('emmit liveStewam');
		io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")});
	})

	proc.stdout.on('data', function(data) {
	  console.log('stdout: ' + data);
	})

	proc.stderr.on('data', function(data) {
	  console.log('stderr: ' + data);
	})

	proc.on('exit', function(code) {
	  console.log('exit code: ' + code);
	})

}

spawnでraspistillコマンドを実行してストリーミングします。

その後、fs.watchFileで、image_stream.jpgを監視。

変更があったら、io.sockets.emitで画像URLと更新時間を送付します。

	proc = spawn('raspistill', args);
	console.log('Watching for changes...');
	app.set('watchingFile', true);

	fs.watchFile(__dirname+'/stream/image_stream.jpg', function(current, previous) {
		console.log('emmit liveStewam');
		io.sockets.emit('liveStream', {url:'image_stream.jpg?_t=' + (Math.random() * 100000), time:dateformat(new Date(), "yyyy/mm/dd HH:MM:ss")});

raspistillコマンドの - tl 500 は電圧等の関係で値調整が必要ですのでご注意を。

次にindex.html(クライアント側)

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>the view from my office </title>
<!-- Bootstrap CSS -->
<link href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet">
<style type="text/css">
#stream {
height: 99%;
margin: 0px auto;
display: block;
margin-top: 20px;
}
</style>
<!-- jQuery -->
<script src="http://code.jquery.com/jquery.js"></script>
<!-- Bootstrap JavaScript -->
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="/socket.io/socket.io.js"></script>
<script>
var socket = io();
socket.on('liveStream', function(data) {
	$('#stream').attr('src', data.url);
	$('#timetext').text(data.time);
	$('.start').hide();
	});
function startStream() {
	socket.emit('start-stream');
	$('.start').hide();
}
</script>
</head>
<body class="container">
<h1 class="text-center">the view from my office
<small>Powered by PI</small>
</h1>
<hr>
<button type="button" id="" class="btn btn-info start" onclick="startStream()">Start Camera</button>
<div class="row">
<img src="" id="stream">
</div>
<div id="timetext" class="text-center"></div>
</body>
</html>

最初にstartStreamで、socket.emitで、"start-stream"を送付します。
後は、socket.onで、"liveStream"を受け取り画像と更新時間を再描画。

socket.on('liveStream', function(data) {
	$('#stream').attr('src', data.url);
	$('#timetext').text(data.time);
	$('.start').hide();
	});
function startStream() {
	socket.emit('start-stream');
	$('.start').hide();

node.jsってこんなに簡単にコーティング出来る。感動。

nohup node ./httpd/liveStreaming/index.js &
で起動します。

ターミナル閉じたいのでnohup にしました。

f:id:m-kei1:20150220133427p:plain

startCameraをクリック

f:id:m-kei1:20150220133433p:plain

オフィスというか僕のデスクからの外の景色です。
ちなみにカメラのびよ~んの奴がうまい事向きを調整できずに逆さカメラになっております

最後にgithubソースコード公開しました。


k1morikawa/RaspberryPI_LiveStreaming · GitHub

次回は、これをインターネットに公開しようと思います。