m5stack.jsを出したので色々遊んでみました。
やっぱりちっちゃいディスプレイがあるので、そこで遊びたいですよね。
画像表示させたいですよね。TVとかyoutubeを流したいですよね。サブディスプレイにしたいですよね
というわけでやってみました。
つくったもの
#m5stack をサブディスプレイとして採用しました #obnizOS pic.twitter.com/T9NbuqUAUI
— kido@IoTエンジニア (@9wick) 2019年8月23日
だいたい60行ぐらいのプログラムです。 お手軽感満載です
かわりにソースコード外で色々頑張ってるところがあります。
しくみ
サブディスプレイのキャプチャを撮ってm5stackで表示しています。
色々小ネタはありますが、基本的にはそれだけです。
これを実現するのに、chrome(HTML)とobnizOSを使っています。
サブディスプレイの画像取得にはchromeのgetDisplayMedia
をつかっています。
最近のブラウザは便利で、ディスプレイのキャプチャまで取れてしまうんですね・・・恐ろしい時代・・・。
流れとしてはこれだけです。
- 仮想サブディスプレイをつくる(今回未実施)
- ディスプレイの内容をHTMLで取得する
- 取得した画像をobnizOSをつかってM5Stackへ転送する
**仮想サブディスプレイをつくる(今回未実施)**のところだけ、よくわからなかったのでリアルディスプレイをつないでごまかしました。世の中には仮想ディスプレイデバイスとかあるっぽいので、それを使えばできるかと思います。(でもホントはソフトでやりたい)
これすげー!探してたけどほんとにあるとは…!ソフトだけだと難しいのかな?
— kido@IoTエンジニア (@9wick) 2019年8月23日
HDMI virtual display https://t.co/iiRKo9jQAU
作り方
まずはm5stackにobnizOSをインストールします。
こちらの記事とか、公式サイトに手順が書かれています。
obnizOSをインストールしたら、htmlアプリを作るだけです。
localhostか、もしくはSSL対応のところにHTMLをホスティングして作ります。
obnizの開発者コンソール内に作るのが楽です。
プログラムとしては、
- スクリーンショットを撮ってvideoタグに描画する
- videoの内容をcanvasに描画する
- canvasの内容をm5stackに描画する
だけです。
プログラムの下準備
HTML上で、canvasとvideoタグを宣言しておきます
<video controls id="v" width="480px" height="270px" autoplay></video>
<canvas id="c" width="320px" height="260px"></canvas>
JavaScript側でも使うので、変数を作っておきます
let canvas = document.getElementById("c");
var video = document.getElementById("v");
スクリーンショットを撮ってvideoタグに描画する
まずはvideoタグにスクリーンショットが入るようにします。
navigator.mediaDevices.getDisplayMedia({audio: false, video: true}).then(stream => {
video.srcObject = stream;
})
これを実行するとchrome上でどの画面を描画するか?のダイアログが出てきて、画面を選ぶことができます。
面白いのがchromeのタブ(バックグラウンド実行も可)を選ぶこともできて、これはこれで色々できちゃうんですね。
ここで画面を選ぶと、その内容がvideoタグに入るようになります。
videoの内容をcanvasに描画する
canvasのdrawImageでそのままかけますので、canvasに描画します。
var ctx1 = canvas.getContext('2d');
ctx1.drawImage(video, 0, 0, 320, 240);
このとき、矩形抽出とかすれば特定領域だけm5stackに表示とかもできます。
2行でできてシンプルですね
canvasの内容をm5stackに描画する
ライブラリを使うので、scriptタグで読み込んでおきましょう
<script src="https://unpkg.com/obniz@2.2.0/obniz.js"></script>
<script src="https://unpkg.com/m5stackjs/m5stack.js"></script>
obnizOSが入ったm5stacktと接続します。
OBNIZ_ID_HEREのところはm5stackにいれたobnizOSの番号を入れてください。
let m5 = new M5Stack('OBNIZ_ID_HERE');
m5.onconnect = async function () {
await m5.m5display.onWait();
...
};
m5stackに描画するには、canvasをdrawするだけです
m5.m5display.draw(ctx1);
これで出来上がりです!
プログラム全体
プログラムとしてはこちらです!
だいたい60行ぐらいかな。
プログラムすべてを表示
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>youtube stack</title>
<script src="https://obniz.io/js/jquery-3.2.1.min.js"></script>
<script src="https://unpkg.com/obniz@2.2.0/obniz.js"></script>
<script src="https://unpkg.com/m5stackjs/m5stack.js"></script>
</head>
<body>
<video controls id="v" width="480px" height="270px" autoplay></video>
<canvas id="c" width="320px" height="260px"></canvas>
<script type="text/javascript">
let canvas = document.getElementById("c");
var video = document.getElementById("v");
let m5 = new M5Stack('OBNIZ_ID_HERE');
m5.onconnect = async function () {
await m5.m5display.onWait();
var ctx1 = canvas.getContext('2d');
while (1) {
ctx1.drawImage(video, 0, 0, 320, 240);
m5.m5display.draw(ctx1);
//描画サイクルが早すぎるとエラーになることがあるので調整
await new Promise(resolve => {
setTimeout(resolve, 100)
});
await m5.pingWait();
}
};
navigator.mediaDevices.getDisplayMedia({audio: false, video: true}).then(stream => {
video.srcObject = stream;
})
</script>
</body>
</html>
サブディスプレイとして活用して遊びましょう!
#m5stack をサブディスプレイとして採用しました #obnizOS pic.twitter.com/T9NbuqUAUI
— kido@IoTエンジニア (@9wick) 2019年8月23日
応用
chromeタブを描画範囲にしてyoutubeを流してみました。
#m5stack の youtube流し、速度早くなった! #obnizOS pic.twitter.com/K6XQinc4ar
— kido@IoTエンジニア (@9wick) 2019年8月23日