Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
8
Help us understand the problem. What is going on with this article?
@n0bisuke

Socket.ioを使ってサーバーの画像が更新されたらブラウザ側も更新させるメモ

More than 3 years have passed since last update.

画像ストリーミング表示っぽいものを作ってみます。

この辺りの続きです。 Node.js v8.4.0です

とりあえずポーリングで対応

フロント側のJavaScriptで定期的に画像を更新するようにします。
ctx.clearRect()ctx.beginPath()で描画をリセットできます。

(canvasあんまり触ってないから使い方怪しいかも)

public/app.js
'use strict';

const canvas = document.getElementById('myCanvas');
if(!canvas || !canvas.getContext) console.log('canvasが使えないよ');

const draw = () => {
    const ctx = canvas.getContext('2d');
    const img = new Image();
    img.src = `img.jpeg?date=${new Date()}`;
    img.onload = () => ctx.drawImage(img, 0, 0);
    return ctx;
}

document.body.addEventListener('click',draw);
setInterval(()=>{
    const ctx = draw();
    ctx.clearRect(0,0,640,600);
    ctx.beginPath();
    console.log('更新');
}, 5000);

img.srcのパス指定でimg.jpeg?date=${new Date()}としていますが、おなじパスだとブラウザによってはキャッシュされてしまうことがあるのでおなじパスにならないようにしてます。

この状態だと結構カクカクします。

CreateJSを利用して性能アップ

このカクカクする感じを解消しようと試してましたが、CreateJSを使ったらいい感じに表示されました。

index.html
<html>
<head>
    <meta charset="utf-8" />
    <title>Nefry BT Camera</title>
</head>

<body style="background-color:#D0D0D0;">
    <canvas id="myCanvas" width="640" height="480" style="background-color:#FFFFFF;"></canvas>
    <script src="https://code.createjs.com/easeljs-0.8.2.min.js"></script>
    <script src="/public/app.js"></script>
</body>
</html>

コードも結構短くなった。

public/app.js
'use strict';

const stage = new createjs.Stage('myCanvas');
const socket = io();

const draw = () => {
    const bmp = new createjs.Bitmap(`/img.jpeg?date=${new Date()}`);
    stage.addChild(bmp);
    createjs.Ticker.on('tick', () => stage.update());
    console.log(`update: ${new Date()}`);
}

setInterval(()=>draw(), 5000);

ICSさんの記事が参考になりました。

Socket.ioを使って画像変更を検知

現状だとポーリングなので余計なリクエストが発生してしまっています。

Socket.ioを使って画像変更を検知します。

↑の記事の続きなのでsocket.ioを追加でインストールします。

npm i --save socket.io
server.js
'use strict';

const fs = require('fs');
const app = require('express')();
const http = require('http').Server(app);
const io = require('socket.io')(http);
const express = require('express');
const PORT = process.env.PORT || 3000;
app.use(express.static(__dirname));

io.on('connection', (socket) => console.log('a user connected')); //socket.ioのコネクション

app.get('/', (req, res) => res.sendFile('./index.thml'));
app.post('/', (req, res) => {
    let buffers = [];
    let cnt = 0;

    req.on('data', (chunk) => {
        buffers.push(chunk);
        console.log(++cnt);
    });

    req.on('end', () => {
        console.log(`[done] Image upload`);
        req.rawBody = Buffer.concat(buffers);
        //書き込み
        fs.writeFile('./img.jpeg', req.rawBody, 'utf-8',(err) => {
            if(err) return;
            console.log(`[done] Image save`);
            io.sockets.emit('new message',{message: `[done] Image save`}); //画像が更新されたことを通知
        });
    });
});

http.listen(PORT, () => console.log(`listening on *:${PORT}`));
public/app.js
'use strict';

const stage = new createjs.Stage('myCanvas');
const socket = io();

const draw = () => {
    const bmp = new createjs.Bitmap(`/img.jpeg?date=${new Date()}`);
    stage.addChild(bmp);
    createjs.Ticker.on('tick', () => stage.update());
    console.log(`update: ${new Date()}`);
}

socket.on('new message', (msg) => draw());

draw(); //初期実行

サーバー側で画像の更新があったらnew messageのイベントが発火し、フロント側ではこのイベントをキャッチしたら画像の更新処理を行います。

これで画像がストリーム表示っぽくなりました。

所感

とりあえずカメラに写っている部屋などを外から監視する仕組みが作れそうです。
socket.ioで直接base64変換した画像データを送るみたいな機能も検討したいです。

8
Help us understand the problem. What is going on with this article?
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
n0bisuke
プロトタイピング専門スクール「プロトアウトスタジオ」で教えたりしてます。 プロフ -> https://dotstud.io/members/n0bisuke
dotstudio
全ての人がモノづくりを楽しむ世界を目指して活動しています。 ( https://dotstud.io ) プロトタイピングスクールの運営をしています。

Comments

No comments
Sign up for free and join this conversation.
Sign Up
If you already have a Qiita account Login
8
Help us understand the problem. What is going on with this article?