🎥

M5CameraやラズパイなどのMJPEGデータを中継するNode.jsサーバ

2 min read

M5Cameraに最初に書き込まれているのは使いやすいけど…

複数からのアクセスでstreamが見れない!

M5Cameraのコード変えてもいいけど…中継するサーバー作って、複数のM5Cameraの映像を管理するのもありかなぁと思い作りました。

環境

M5Cameraに書き込むコード

https://github.com/tkyko13/M5CameraMDNS

自分が作ったMDNSに対応させたM5Camera用のプラグラムです

最初にあったコードに追記する形なのでできることは変わりません

Node.js側のソースコード

const express = require('express');
const http = require('http');
const app = express();
const mjpeg2jpegs = require('mjpeg2jpegs');
const mjpegServer = require('mjpeg-server');

const PORT = 8800;

// 複数のクライアントに対応
let buff = Buffer.alloc(0);

// サーバー開始直後にm5cameraから画像取得処理開始
const httpOption = {
	hostname: 'm5camera_1.local',
	path: '/stream',
	port: 81,
	responseType: 'arraybuffer',
	headers: {
		'Content-Type': 'image/jpeg',
	},
};
const httpHandler = mjpeg2jpegs((mjpegRes) => {
	let processBuff = Buffer.alloc(0);
	mjpegRes.on('imageData', (data) => {
		// 送られ続けているデータをつなげてためていく
		processBuff = Buffer.concat([processBuff, data]);
	});
	mjpegRes.on('imageEnd', () => {
		// 1枚の画像データが完成のタイミング
		buff = Buffer.concat([processBuff]);
		processBuff = Buffer.alloc(0);
	});
});
http.request(httpOption, httpHandler).end();

// motionJpegサーバ
app.get('/', async (req, res) => {
	// モーションjpegサーバーの作成 リクエストごとに作成
	const mjpegReqHandler = mjpegServer.createReqHandler(req, res);

	let c = 0;
	const interval = setInterval(() => {
		mjpegReqHandler.write(buff);
		console.log(c++); // ここの無限ループが抜けられない
		
		if (false) {// クライアントが切断したらここを通らせたい
			mjpegReqHandler.close();
			clearInterval(interval);
		}
	}, 100);
});

app.listen(PORT, () => {
	console.log('Running at http://localhost:' + PORT);
});

mjpeg2jpegs を使ってM5Cameraの映像バッファーをまずは取得する

mjpeg-server でそのバッファーを配信

無限ループが終わらせられなかった…

コード内にも書いてある部分を抜けられなかった

サーバにアクセスし、別のページとかに遷移しちゃってもカウントが止まっていない

https://github.com/gluxon/node-mjpeg-server/blob/master/examples/server.js

ライブラリのexampleにも無限に配信するものがあるわけではなく、配信用途にMJPEGはあってないのかなぁと思いました

おまけ MJPEGをWebサイトで見る

<img src="http://localhost:8800"/>
<!-- or -->
<img src="http://m5camera_1.local:81/stream"/>

簡単ですね

Discussion

ログインするとコメントできます