CreateJS で背景前景ともに動かしながら曇りガラス的表現をする
はじめに
磨りガラスってこんなかんじ。
photo by Johnny Jet
友人氏がそういうのをやりたい、と言っていたのを思い出してやってみました。
完成品はこちら
コード
あげてあります
環境
- EaselJS 0.8.0
参考にしたもの
Cacheについて
- EaselJS/Cache.html at master · CreateJS/EaselJS · GitHub
- CreateJステージのキャプチャーと複数コンテナを合成し画像に変換|POPS-WEB
DisplayObject.cache()
は、オフスクリーンレンダリング用に document.createElement('canvas')
して、そこにデータを書き込む操作で、そこに書き込んだ物をなんども使い回したり、できあがった画像全体にポストエフェクトを掛けたりするのに使います。
上記ブログでは、DisplayObject.cacheCanvas
でオフスクリーンレンダされている画像にアクセスできることが説明されています。スーパーナイスです。
blurのかけ方、マスクの仕方
上で先に書いちゃいましたが、.cache()
関数でオフスクリーンレンダした結果に対して、ブラーをかけたりできます。
このサンプルではDisplayObject.mask
に createjs.Shape
のオブジェクトを登録することで、Shapeの形状に切り抜いています。graphics.drawHOGE()
で描ける単純な形状で抜きたい場合はこちら。
こちらの AlphaMaskFilter
では、 フィルタになるアルファを持った絵を作り(最終的にcacheCanvasを入力に使うので、Shape等にかぎらない)、そのアルファチャネルを使って対象のDisplayObjectにマスクをかけます。アルファを持つ画像等をもとに複雑なマスキングをしたい場合はこちら。
最後に
今回やっていること図示するとこんな感じです。詳しくはコードをご参照ください。
ブラー元の画像を作って cacheCanvas で引っこ抜くために 1キャッシュ, ブラーをかけてマスクで抜くためにもう1キャッシュ、計2キャッシュ使いそれらを毎フレーム更新するのでやや重いのが問題です。
どうにか改善したいのですが…
html から node.js を介して oF の画像処理をコントロールし、ブラウザ上で閲覧する
はじめに
前回の記事で ycapture を使って、oF の描画内容を Windows のビデオデバイスとして流すことで、ブラウザからも見ることが出来るようにする手法について紹介しました。
前回やったことを図でまとめるとこんな感じ(再掲)
ブラウザからoFアプリをコントロールする
今回はそれを発展させて、HTML側からカメラエフェクトを変更・調整できるようにしてみます。
できあがりはこんな感じ。ブラウザから、ネイティブアプリ(oF)に指令を送って、エフェクトを調整しています。
完成時のシステムは以下の様になります。
ブラウザで選んだエフェクトの種類や強度の情報をWebSocket で Node.js にわたし、 Node.js からは OSCでリレーしてエフェクトの種類の情報をoFに渡します
環境とつかったもの
- Windows 7
- Visual Studio Express 2012
- openFrameworks v0.8.4
- ofxOSC
- ofxCv
- ofxOpenCV
- ycapture.dll
- node.js v0.10.29
- node-osc
- express
- socket.io
あげてあります
今回のコードは、 node.js(およびhtml) の部分と、 oFの部分で二つに分けてアップしてあります。 oFのプロジェクトは ycapture の存在を前提にしているので、前回の記事を参考に導入してみてください。
ycapture に関しては前回記事参照
ycapture をつかって画像処理の結果を windwos のビデオデバイスとして流すやり方については、前回から変わっていません。今回は、三つの登場人物間で増えた通信部についてメモをしておきます。
html - node.js 側
- NORMAL(エフェクトなし)
- CANNY (エッジ抽出)
- BLUR (ぼかし)
のラジオボタンを選択すると、どれが選ばれたかをNode.js 側に伝えます。
また、CANNY と BLUR については、その効果の効きをレンジスライダーで調整してNode.js側に伝えます。
これらの通信には、エフェクトの効きをリアルタイムに反映させたかったので、WebSocket(Socket.io) を利用しています。Socket.io の使い方については特殊なことはしていないので、ソースコードをご参考下さい。
要素使いこなし
<p><label>THRESH1<input type="range" name="canny_thresh1" min ="1" max="400"></label></p> // 1~400 の間を、1刻みで選択出来る。 <p><label>SIZE<input type="range" name="blur_size" min="1" max="201" step="2"></label></p> // 1~201 の間を、2刻みで選択出来る
後者が特徴的です。ofxCv::blur
は内部的に cv::GaussianBlur
を呼んでいて、ガウシアンカーネルサイズは奇数で無くてはいけません。そこで、上記のような指定にすることで、<input>
の出力を奇数に限定しています。
また、<input type="range">
要素は、value が string となっているため、Socket.io で送り込む際に、number要素に変換しておきます。
document.cv_effect.blur_size.oninput = function() { // ドラッグ中も数値を取りたかったら oninputを使う // リリース時のみ取りたかったら onchange socket.emit('blur size', parseInt(this.value)); }
node.js - oF 側
node.js 側
Socket.io でブラウザから送られてくるメッセージをoscに載せ替えて送り出しています
socket.on('blur size', function(value){ oscclient.send('/blursize', value); });
oF 側
OSCのメッセージを受け取って、CVのエフェクトを切り替えたり、効果の強さを調整したりします
// ofApp.cpp while(oscReceiver.hasWaitingMessages()){ ofxOscMessage m; oscReceiver.getNextMessage(&m); std::string oscaddress = m.getAddress(); if(oscaddress == "/changeeffect"){ std::string typeStr = m.getArgAsString(0); if(typeStr == "non") { effectType = EffectType::NONE; } else if(typeStr == "canny" ) { effectType = EffectType::CANNY; } else if(typeStr == "blur" ) { effectType = EffectType::BLUR; } else { } } /*中略*/ else if(oscaddress == "/blursize") { blurSize = m.getArgAsInt32(0); } // このあと effectType や blurSize を使う }
追記
本記事の投稿後、 凹先生から助言をいただきました。
@izmhrats あと、この構成なら C++ で websocket 使ったほうがクールかもと思った(https://t.co/0U6ohrlwnF)。
— 凹 (@hecomi) 2015, 1月 13
ofxLibWebsockets 試してみたところ確かにお手軽に oF 上で WebSocket が扱えて、Node.js が不要になるので良いと思いました!
最後に
WebRTC を使ってビデオチャットにする
今回は扱っていませんが、今回の物に PeerJS (WebRTC)を加えると、画面エフェクトが可能なビデオチャットシステムが完成しますね。
他プラットフォーム
前回ご紹介した内容は、デバイスやOSの仕組みが関わるところだったので Windows 限定でしたが、今回ご紹介した内容は node.js と oFのaddonで出来るので、すべてのプラットフォームで実現可能です。 前回の記事で言う ycapture の仕事を linuxやMac OSX でやる手法についても、前回の記事の最後に調査だけしてあるので、それと組み合わせることで、他のプラットフォームでも同様の機能を実現できるのではと思います。
ycapture で OpenCV での処理結果を Windows のビデオソースとしてブラウザに流し込む
はじめに
WebRTC を使ってビデオチャットアプリを作る際に、ビデオ画像にエフェクトをかけたくなりました。モザイクとか、ブラーとか、漫画カメラとか。
ブラウザ上でJavaScriptでごりごり画像処理をするのはさすがに厳しそうですので、画像処理を行うのは別のアプリケーションで行うことにしました。
最終的に WebRTC で MediaStream として扱うことを考えると、画像処理の結果が通常のWebカメラと同様に navigator.getUserMedia()
できれば一番手っ取り早いんじゃないかなーと思っていろいろ手法を探してみました。
便利なソフトを教えていただいた
しかし調べれば調べるほど、Windows上だと DirectShowのお勉強しなきゃとかつらそうな気配が漂っていたのですが、Twitterに泣きついたところ、@jnakano さんが ycapture(わいきゃぷちゃ) の存在を教えて下さいました。
@izmhrats http://t.co/0hLZJ5ZUUd これだ。
— Junichi 'DJ' Nakano (@jnakano) January 9, 2015
ycapture(わいきゃぷちゃ)
説明から引用
ycaptureとは、WindowsのVideo Capture Sourceのような振る舞いをするDLL(の基本ソース)です。このDLLを使用すると、あたかもビデオキャプチャデバイスのように、任意のプログラムからビデオデータを供給することができます。
これだー!と言うことで、今回試してみました。開発者の谷沢さん、ありがとうございます。
開発の前に
今回やりたいこと
注意
今回のアプローチがベストかどうかはケースバイケースだと思うので、手法の一つとしてご参考にしていただければと思います
環境
- Windows 7 / 8.1
- Visual Studio Express 2012 / Community 2013
- Chrome
ycaptureのビルドは、
- Windows7 + Visual Studio Express 2012
- Windows8.1 + Visual Studio Community 2013
の2つの組み合わせで確認しています。openFrameworks に関しては、Visual Studio 版が 2012(v110) にしか対応していないため、今回のシステム全体としては、Visual Studio 2012 を利用しています。
ycapture の準備
公式に載っている利用法に従って下さい。公式ページでは VS2008で、と書いてありますが上記の通りの環境でもビルド & 利用可能でした。以下、ポイントだけメモっておきます。
Release か Debug か。ビルドの種類とパスの設定に注意。
Visual Studio は ライブラリ類のパスを通すのが面倒なので、私は Release ビルドに統一してやっています。Visual Studioのプロパティをいじる際は、毎回 Configuration の表示に気をつけましょう。
Windows SDK を導入し、DirectShowの baseclasses をビルドして静的ライブラリを作る
Windows SDK アーカイブ – Windows デベロッパー センター
今回はこちらの Windows 7 および .NET Framework 3.5 SP1 用 Windows SDK を使っています。
baseclasses ライブラリのソリューションを Visual Studio 2012(2013) で開こうとすると、変換の際に大量の警告が出ますが、ビルドは出来ます。
配布されている ycapture プロジェクトのビルド準備
ycaptureプロジェクトのプロパティで、インクルードやリンクがうまくいくよう設定を変更します。先述の DirectShow/baseclasses の在処を教えてあげます(配布された状態だと、Windows SDKのバージョンが違ったりしています)
私の場合は以下の通り
追加のインクルードディレクトリ
C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\baseclasses;
追加のライブラリディレクトリ
C:\Program Files\Microsoft SDKs\Windows\v7.0\Samples\multimedia\directshow\baseclasses\Release;
これでビルドが出来ます。
ycaptureclient と testclienet のビルド
この二つは、配布状態のままでビルド可能です。
testclientは、ソリューション内でycaptureclientに対してプロジェクトの依存関係が組まれているので、特にライブラリの場所とか気にしなくて大丈夫なようです。
ycapture.dll の登録
regsvr32.exe を使ってdllを登録する際は、 powershell/cmd を管理者権限で立ち上げないと怒られます。
>regsvr32.exe ycapture.dll
サンプルを試す
ycapture で配布されている testclient で、以下の流れが確認出来ます。
- testclient を起動します。
- 受け側として、ブラウザで https://simpl.info/getusermedia/sources/ を開きます。
navigator.getUserMedia
のサンプルアプリです。
受け側はSkypeなどのアプリでももちろん大丈夫です。- 画面に、testclientが流している赤い帯が表示されれば成功です
testclient が生成するカメラが見つからないときがある
ドライバの読み込み順の関係かキャッシュか正確なことは分かりませんが、作った仮想カメラがクライアントから見つからないことがあります。こういうときは、ページのリロードや、既に刺さっているウェブカムの抜き差しなどをすると、見つかるようになります。
ycapture を oF 内で利用する
ycapture を oF 内で利用する事で、oF での描画結果やCVを使った画像処理の結果を、仮想カメラデバイスとして流すことが出来るようになります。
プロジェクトの準備
ここでは Visual Studio での oF プロジェクトの生成等については割愛いたします。
以下の点をプロジェクトのプロパティに設定していきます
- baseclasses/ycapture のビルドにあわせて、configuration を Release にする
- 追加のインクルードディレクトリに、ycaptureとycaptureclient のソースコードがある場所を追加する
<ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\ycaptureclient <ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\ycapture
- 追加のライブラリディレクトリに、ycapture/ycaptureclientのビルド結果がある場所を追加する
<ycaptureをおいた場所>\ycapture-src-0.1.1\ycapture\Release
- ライブラリの入力に、以下の物を追加する
ycapture.lib ycaptureclient.lib
コード
ycapture さんで配布されているtestclient を参考に書いていきます。
// ofApp.h // 前略 #include "ofxCv.h" #include "CaptureSender.h" #include "ycapture.h" class ofApp : public ofBaseApp { public: // 中略 ofVideoGrabber cam; ofImage raw; ofImage blur; CaptureSender *sender; // ycaptureのオブジェクト };
// ofApp.cpp int CAM_WIDTH = 640; int CAM_HEIGHT = 480; unsigned long avgTimePF = 1000 / 30; // 30fps ストリームのタイミングを作るのに使うらしいが詳細不明 void ofApp:setup(){ cam.initGrabber(CAM_WIDTH, CAM_HEIGHT); // カメラの初期化 sender = new CaptureSender(CS_SHARED_PATH, CS_EVENT_WRITE, CS_EVENT_READ); // ycaptureのセットアップ // 後略 } void ofApp::update(){ cam.update(); if(cam.isFrameNew()){ raw.setFromPixels(cam.getPixels(), CAM_WIDTH, CAM_HEIGHT, OF_IMAGE_COLOR); // カメラ画像をコピー raw.mirror(1, 0); // そのまま送るとブラウザ側で垂直方向に反転する ofxCv::blur(raw, blur, 51); // ブラーをかけてみるテスト HRESULT hr = sender->Send(counter * avgTimePF, CAM_WIDTH, CAM_HEIGHT, blur.getPixels() ); //★★ここがポイント★★ // 後略 } } void ofApp::draw() { cam.draw(0, 0); }
要するに、何かしらの方法で画像を作った後、 RGBの順の unsigned char
配列にして、sender->Send()
すれば良いようです。oFやCVには、RGBの順の unsigned char
配列 への変換関数が用意されているので楽ちんです。
さいごに
ウェブブラウザ上で、oFで処理した結果の画像が見られれば完成です。oFのウィンドウに表示されているカメラのスルー画と並べて見ても、遅れは感じられません。良い感じ。
次は、せっかくブラウザ上でやっているので、ブラウザでのユーザの入力を受け付けて、エフェクトを変更したりする仕組みを作ってみようと思います。
他プラットフォーム
Linuxの場合
余り詳しくないので間違いがあるといけないのですが、、Linux環境だと、gstreamer や V4L2loopback といったモジュールを使うと、割と簡単に動画ストリームをビデオデバイスとして取り扱うことが出来るようです。実際、openFrameworksの addons に arturoc/ofxGstV4L2Sink · GitHub と言う物があって、リポジトリのREADMEによれば、
Uses v4l2sink gst element to create a virtual device which can be used as a camera in any application that supports v4l2
とのことで、今回狙っていることが出来そうです。ただし私は試していません。
Mac OSX の場合
rsodre/ofxFakam · GitHub と言う物があり、これも
ofxFakam is an Open Frameworks addon that streams screen data to a fake camera driver.
ということで、狙っていることが出来そうです。ただし私は試していません。
FFmpegで WebM の半透過動画を作成し、Chromeで再生する
はじめに
ウェブアプリで画面全体にわたるようなリッチなエフェクトを掛ける手段のひとつとして、デザイナさんに作ってもらう動画(たとえばAfter Effectsで)をそのまま使う、なんてことは出来ないかと考えてトライしてみました。
HTML要素の上に半透過の動画を <video>
要素で置くことで、もとのHTMLを動画で演出、みたいなことができています。
できあがった物はこちらで確認出来ます
ブラウザは Chrome しか対応しておりません!ご注意。
環境
- Windows 7 pro 64bit
- Google Chrome
- After Effects CS 5.5
- FFmpeg 2.5.1
ちなみに、WebM を透過して表示できるのは、PC/Mac のChrome だけのようです。悪しからず。
Firefox@Mac だと、アルファチャンネルが捨てられて、全画面カラフルに塗りつぶされます
元ネタ
今回の記事は、こちらの記事を足がかりに、追加でいろいろ調べてまとめた物になります。
動画の作り方
普段からデザイナさんに After Effects で動画を作ってもらっているので、この記事では After Effects を使ってにアルファ付き WebM 動画を作ってみます。
もしかしたら最新の After Effects では既にアルファ付き WebM の書き出しに対応しているかもしれませんが、私が使える 5.5 では出来なかったので、エンコードには FFmpeg に梱包されている vp8 (libvpx) を利用します。
After Effects でコンポジション作成
新規プロジェクトから普通にコンポジションを作成し、そこに要素・アニメーションを加えていきます。半透過のテストをしたかったので、アルファが変わったり、淡いグラデーションがかかっているような動画を作ろうと思い、今回はこちらの記事を参考にサンプルを作ってみました
WebM は 60fps にも対応しているので、コンポジションのフレームレート設定を 60fpsにしました。
背景はデフォルトの黒です。
After Effects でアルファ付き QuickTime Movie 書き出し
FFmpegでWebMにエンコードする元になる、アルファ付きの動画を出力します。AVI と QuickTime形式がアルファ付きに対応しているようですが、AVIだと尋常じゃない容量になるので、QuickTimeで書き出しますことにします。
対象のコンポジションを選択した状態で コンポジション > レンダーキューに追加
を選ぶと、レンダーキューウィンドウにひとつ、レンダリング処理が追加されます。
そのレンダーキューの "出力モジュール" を選択して、下記のような設定にします。ポイントは以下の3点です
カラーを「合成チャンネル(マットあり)」 にすると、アルファチャンネルだけで無く、RGBのレイヤーも調整された動画が描き出されます。 出力された MOV ファイル単体を QuickTime で再生するときはこれで良いのですが、WebM にエンコードして他の画面に合成した際に、色味が暗い感じになってしまいます。
ストレートアルファとプリマルチプライド・アルファ(合成チャンネル)の違いは、こちらのページが詳しいです
あとは、出力先で適当に場所を決め、ファイル名を決めてレンダリングを行います。
FFmpeg で WebM にエンコード
インストール
FFmpegは別途インストールしておいてください。 Windowsの場合は、binaryをダウンロードしてきて、どこか適当な場所に解凍し、システム環境変数の path に、ffmpeg/bin
のパスを通すと、コマンドプロンプト/PowerShell からコマンドをたたけるようになります。
エンコード
先ほど出力した mov ファイルのあるディレクトリに移動後、以下のコマンドでエンコードを行います。
ffmpeg -i webmtest.mov -crf 10 -b:v 1M webmtest.webm
オプションはいまいちよく理解出来ていないのですが、下記サイト様に説明が載っています。要は、オプション指定しないと結構画質が悪くなるので、VBR(可変ビットレート) の目標値 (1Mbits/s) と、VBRする際の最低品質保障 (4-63 での 10) を指定してね、という感じみたいです。
これでアルファ付きの WebM 動画ファイルが書き出されました。このファイルは、 Chrome にぽいっと投げ込むと、その場で再生してもらえます。が、背景がとくにないので真っ黒に表示され、このままでは透過できているのか分かりません。
再生
というわけで、背景と適当なHTML要素を加えた上に透過動画をおいてみたのが、一番初めの作例になります。
画質優先で連番.tga を使う場合
AfterEffects から QuickTime(MOV) で書き出した時点で、圧縮率を最低にしたとしても、最終的なWebMにたどり着く前に何かしらの圧縮が入ってしまっていることになります。画質最高とは言えません。
そこで、一度無圧縮のアルファチャネル付き連番画像を書き出し、それから アルファ付き WebM をエンコードする、というパスを取ることもできます。
連番 TGA 書き出し
新しいレンダリングキューを作成し、出力モジュールを以下の様に設定します。
- 形式:Targa シーケンス
- チャンネル: RGB + アルファ
- カラー: ストレート(マットなし)
- 形式オプション
- 解像度 32bits/pixel (アルファチャネル付き)
- 圧縮はなし!
その上でレンダリングすると、だだーっとTGAファイルが書き出されます。1920x1080、32bit ですと 1枚 8MB ほどもあるのでかなりつらい感じになります。。。
連番 TGA から WebM にエンコードする
入力を、 MOV から 連番tga に変えるだけです。
ffmpeg -r 60 -i webmtest_%05d.tga -crf 10 -b:v 1M webmtest.webm
tga ファイルのサイズは膨大になりましたが、vp8 としては同じ圧縮を行うので、最終的に出てくる WebM ファイルの容量は、MOV を経由した場合と同程度になります。
さいごに
Chrome 限定な上、 WebM ってぶっちゃけそんなに流行っている気配も無いので、この手法もこれといって使えるシーンが無い可能性は大きいと思います。
けどせっかくちゃんと出来るようになったので、まとめておきました。ちゃんちゃん。
(タブレットで) 鏡餅を光らせて新年を迎えましょう | 実装編
はじめに
前回は、おうちハック Advent Calendar 2014 向けとして記事を書きました。そちらでは全体の紹介と、取り組んだ背景みたいなところにフォーカスして書いたので、今回は自分向けに実装で手こずったところ等をメモしていきます。自分用のメモなので雑多でごめんなさい。
目次
- socket.io でルーム管理。おもち側が閉じたら、繋いでいるコントローラに伝達する仕組みなど
- 様々なブラウザ・解像度への対応 (軽めに…
- さくらのVPSに Node.js アプリをデプロイする際のTips
- そのほか細かい技
おさらいのコード
記事中にコードを展開していくとバカ長くなりそうなので、言及場所にリンクを貼るスタイル。
おさらいの動画
おさらいのシステム図
socket.io でルーム管理。おもち側が閉じたら、繋いでいるコントローラに伝達する仕組みなど
前回の記事でもちらっと書きましたが、今回の案件、本来なら(おそらく) WebRTC を使ってやるべき案件です。光る端末に対し、リモコンが直接指示を出します。基本は1対1で、始まった後は間にサーバが挟まっている必要はありません。
しかし今回は、自分の不勉強のため短いスパンで WebRTC を使いこなせそうになかったので、使ったことのあるsocket.io を使い、間にサーバが挟まるシステムにしました。そのため、利用者が増えると明らかに不利です。アドベントカレンダー向けのネタアプリですので勘弁してください。
そんな中でも一応こだわって頑張った辺りについてメモしておきます。
room名によるおもちの重複防止
おもちとコントローラの対応付けは、socket.ioが備えているroomの仕組みを使って行っています。roomは一般的なチャットルームを実装するための基本機能なのですが、
- 存在しないルーム名でjoinしたら、新たにルームが作られる
- 既存のルーム名でjoinしたら、既存のルームに入る
という動作になっております。
OMOCHI HACK ではこの仕組みを利用しつつ「おもちは必ずオリジナルな名前のルームとして作って、そこにコントローラが名指しでjoinする」仕組みとし、おもちの名前は重複を許さないことにしました。
- おもち側で存在しないルーム名で入ろうとしたら、joinする → 新たにルームが作られる
- おもち側で既存のルーム名で入ろうとしたら、既に使われている名前であると警告を出し、再入力を促す
この辺りの処理は、 server.js L62 - L112 あたり にコーディングしてあります。socket.ioのルーム管理とは別に、独自に現存するおもちのリストを管理することで実現しています。
おもち死亡のおしらせをコントローラ側に通知する
通常利用だと、おもち側が閉じるケースとして以下の様な物があります
これらを検出したうえで、以下の事をやらなければなりません
- ルーム(おもち)をリストから削除する(利用された名前がたまってしまわないよう)
- おもちが消えたことをコントローラに通知する
window.onpagehide を利用する
- ページをリロードする
- ブラウザの戻るボタンを利用するなどページ遷移を行う
- タブを閉じる
この3パタンについては、window.onpagehide
で検出できます。はじめ window.onbeforeunload
で書いていたのですが、Safari@iOS8 ではこのイベントが使われなくなって居ることを知り、pagehide に書き換えています。
この辺りの処理は、light.js L133 あたり にコーディングしてあります
socket.io の disconnect イベントを検出する
この2パタンの場合、私が調べた限りでは ウェブアプリがそれを検出して何かする、というのが出来ませんでした。しかし、socket.io の方で、クライアント(ここではおもち)が不活性な状態を検出してdisconnect イベントとして処理する仕組みがあるようで、それを利用する事にしました。
具体的には、disconnectイベントを送ってきたsocketのidを調べて、それがおもちリスト(コード内では lightlist
)に存在するか調べ、していたら削除する、と言う物です
この辺りの処理は server.js L49 - L55 あたりにコーディングしています
イベントを拾えるケース
- 別の名前のおもちを作り直す
最後のパタンは、サーバ側で処理しています。自分が既におもちとしてroom名を持っていて、それと同じ名前で作ろうとした場合は、何もせず既存のroomを利用します。新しい名前を指定した場合は、さっきまで使っていたroomを破棄し、新しいroomを作ります。
この辺りの処理は、 server.js L105 - L109 あたりでコーディングしています。
おもちが消えたことをコントローラに通知する
上記パタンでおもちが消えたとき、コントローラ側は、カラーコントロールのUIがdisableされ、再度おもちの名前入力を要求される画面になります。これで、接続が切れたことをコントローラ側からも認識出来ます。この辺りの処理は sever.js L138 と controller.js L123 にコーディングしてあります。
様々なブラウザ・解像度への対応 (軽めに…
ちまたのウェブデザイナ、ウェブコーダ様方にあたられましては、日々多様化するディスプレイの解像度や、ブラウザごとの微妙に異なるCSSの解釈に日々頭を悩ませていることと存じ上げますが、私も今回のアプリを作り上げるに当たりまして、「出来る範囲で・時間が許す範囲で」広めに対応を取ってみたところです
動作確認しているのは以下の環境
- PC
- Mobile
です。すべて最新の物です。
レスポンシブ的CSS切り分け
@media screen and (min-width: 320px) and (max-width: 480px)
的な物を使う
vendor prefix
-webkit-transform
-moz-transform
とか。
ブラウザごとの対応状況を調べられる。おなじ webkit でも、Chromeではつかえて、 safari@iOS じゃ使えない、とかかなりよくある。
Chrome for Android で border-radius
が微妙に効かない件
コントローラの円形のカラーピッカーを描くのに <div>
に対して四隅50% でradius をかけようとしたが、Androidでだけうまくいかない。
ここを参考に修正
.selector { /* だめ */ border-radius: 50%; /* だめ */ border-top-left-radius: 50%; border-top-right-radius: 50%; border-bottom-left-radius: 50%; border-bottom-right-radius: 50%; /* OK */ border-top-left-radius: 50%; border-top-right-radius: 50%; border-bottom-left-radius: 50%; border-bottom-right-radius: 49.9%; /* ここがポイント */ /* これでもOK */ border-radius: 50% 50% 50% 49.9%; }
この記事では Galaxy S4 で、 と言っている。私の場合は Nexus7 (2013)。機種依存かもしれない。
さくらのVPSに Node.js アプリをデプロイする際のTips
基本
forever さまさまです。
この記事では /etc/nginx/conf.d/
内にリバースプロキシの設定を書いていますが、
/etc/nginx/sites-available/
内に今回のアプリ用の新しい設定ファイルを作っておき/etc/nginx/sites-enabled/
にシンボリックリンク しておくのがいまどき、なはず
自分が作ったサイトの設定ファイルはこんな感じ
# /etc/nginx/sites-available/omochi_hack upstream omochi { server localhost:3000; } server { listen 80; server_name omochi.izmiz.me; proxy_redirect off; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-Host $host; proxy_set_header X-Forwarded-Server $host; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; location / { proxy_pass http://omochi/; } }
VPSのポート設定
そういえば以前iptablesで厳しくポートを絞っていたのを忘れていました。express が ポート3000番でサーバをあげているので、あけてあげなくちゃいけません。
sudo ufw allow 3000/tcp
おなまえ.com のDNS設定
リバースプロキシに設定した omochi.izmiz.me
がちゃんと解決出来るよう、DNSに覚えていただきます
おなまえ.com > ログイン > 今回のドメイン > (タブ)ドメイン設定 > DNS関連機能設定 > 今回のドメインを選んで「次へ進む」 > DNSレコード設定
ログインした状態で直リンク > https://www.onamae.com/domain/navi/dns_controll/input
普通にたどるととんでもない階層にいます。ほとんどここしか使わないのに…!
ここに、 nginx の sites-availabe に設定した server_name を登録します。
以上
以上で、 http://omochi.izmiz.me にアクセスすると、 さくらVPS内の expressが立てている 3000 番ポートで動いている OMOCHI HACK アプリにアクセス出来るようになりました。
そのほか細かい技
今回のアプリで参考にさせていただいたその他のノウハウをまとめておきます
Canvas + image でカラーピッカー
letter-spacing
したテキストをセンタリングする
letter-spacing: 1em
すると、文末にも1文字スペースが空いてしまうので、その分文末に負のマージンを与えるか、文の頭に正のマージンを与える
ブラウザの「ホーム画面に追加」を利用する
これをしてホーム画面からアイコンタップで起動すると、全画面でアプリが開きます。ここで登録されるアイコンについての覚え書き
log4js でログ取り
ロギングのセッティングを json で外部化出来るのが素敵。
内で1行のテキストを垂直方向にセンタリング
.selector {
height: 100px;
line-height: 100px; // height と line-height に同じ値を指定する
}
JavaScriptで HSV -> RGB 変換
jQuery の .delay()
が便利
- jQuery で5秒後とかに addClass したいとき · Issue #61 · shikakun/tips · GitHub
- jQueryでリストを一つずつ遅延して表示する | webOpixel
jQuery .val()
で form の値を取得
jQuery で セレクターを取得
$something.selector
で取得 出来るのだけど、 deprecated. どうしましょう。今回使ってしまいました。
カラーホイールの絵の描き方
さいごに
今回、Advent Calendar締切ドリブンで、UI、通信、サーバサイド、サーバへのアプリのデプロイ と1人で通貫でやってみました。できあがった物はまぁしょぼいのですが、個人的には非常に大変でした。良い経験になりました。
.selector { height: 100px; line-height: 100px; // height と line-height に同じ値を指定する }
JavaScriptで HSV -> RGB 変換
jQuery の .delay()
が便利
- jQuery で5秒後とかに addClass したいとき · Issue #61 · shikakun/tips · GitHub
- jQueryでリストを一つずつ遅延して表示する | webOpixel
jQuery .val()
で form の値を取得
jQuery で セレクターを取得
$something.selector
で取得 出来るのだけど、 deprecated. どうしましょう。今回使ってしまいました。
カラーホイールの絵の描き方
さいごに
今回、Advent Calendar締切ドリブンで、UI、通信、サーバサイド、サーバへのアプリのデプロイ と1人で通貫でやってみました。できあがった物はまぁしょぼいのですが、個人的には非常に大変でした。良い経験になりました。
(タブレットで) 鏡餅を光らせて新年を迎えましょう
この記事は おうちハック Advent Calendar 2014 25日目(なんと最終日!)の記事です。 前日は @K-A-Z さんの 「Arduino+Raspberrypi+GoBotで恋人たちの聖夜を支援する - Qiita」 でした。
ベッドイン検知、まじめなライフログとして王道な利用法も出来る気がします。わくわくしますね。
はじめに
今年は業務でウェブのクライアント…特にUI周りを作る機会が多かったのですが、自分でサーバサイドから通信そしてUIまでアプリを全部作りきる、ということをやったことが無かったので、アドベントカレンダー締切ドリブンでやってみようと決めました。
正直、アドベントカレンダーだったら何でも良かった のですが、リストをざーっと見てみると、どうも敷居が高い感じでちょいと難しい。そんななか「おうちハック」という響きの緩さに「これならいけるんちゃうか…」とつられてみたところです。ネタはそこから考えました 。
おうちハック Advent Calendar さん、登録した時点で最終日しか空きがなかったので、クリスマスは終わったことにして日本人らしくお正月ネタにしよう、おもちじゃん、光ったら素敵じゃん、やったー!\(^_^)/
というわけで、おもちを光らせることにしました。
できたものの紹介
使い方を動画で紹介します。
※注記: OMOCHI 単体でも、じんわりと色と背景が変わっていくオートモードでお楽しみいただけます!
公開してます
PCからももちろん利用できます。ノートPCならお餅をのっけるのも可能ですね!
負荷とかセキュリティとかはわかりません!重かったり落ちてたらすみません。
システム構成
構成は下図のようになっています。OMOCHI側、CONTROLLER側のUI、ブラウザでそれぞれのアドレスにアクセスするとウェブアプリとして表示されその場で使用できます。OMOCHI側は新規作成時に固有の名前をつける必要があります。
上の動画にもありましたとおり、コントローラからおもちの光らせ方をコントロールできます。この用法だと 「明らかにWebRTCだろ」 というおしかりを受けそうですが、甘んじて受け入れます。WebRTCに一瞬トライしたのですが、 難しそうだったのでパスしました 。来年頑張ります!
ソースコード
あげてあります。
使った鏡餅
- 出版社/メーカー: 越後製菓
- 発売日: 2012/12/10
- メディア: 食品&飲料
- この商品を含むブログを見る
厳密にはこれではないのですが、10インチiPadには「5号」サイズの鏡餅が良かったです!この大きさになると台座も付いてくるので、トップの写真のようにグッと雰囲気が増します。
一応まじめらしい背景
今回のプロジェクトの背景として「おうちハック」の視点から見て2点、抜き出してまとめてみました。
余ったスマホ活用
ここ数年で一気にタブレットやスマートフォンが普及し、世代交代も速いため、1人1台や2台にとどまらず、古くなって引出にしまっている端末もたくさん持っている様な状況が(一部のギークの間では)普通になってきたように思います。
Arduino などを使うと従来より非常に簡単にフィジカルな入出力が可能で、しかもネットにつながったツールを作り出すことが出来ますが、入出力の自由度を下げてタッチや液晶表示などに限定して良いケースなら、余剰のスマホや利用頻度のひくいタブレットは 超高性能 なネットワークのノードになります。そしてソフトウェアのコーディングだけで済むので、敷居もグッと下がります。
こういったムーブメントは既にかなり広がってきていて、余ったスマホを監視カメラ代わりに利用するのは非常にメジャーです。また、高性能なプロセッサを小型な信号処理部として活用することで、筋電義手を材料費3万円ほどで作ろう、というプロジェクトも動いています。
余ったスマホ、スゴイです。専用のデバイスを買わなくても、家に有るもので皆さん楽しめます。
つながり感通信
おうちをハックするので、ハックして/されて嬉しいのが自分だけじゃつまらないです。家には自分の家族も居ますし、また、遠く離れた生まれ故郷の実家には、自分の両親もいます。そんな 「おうち」どうしをつなげるような道具 が欲しいなぁ、と思い、今回ネットワーク越しのコントローラ機能を実装しました。
似たようなプロジェクトで有名どころだと、NTT研究所の一連の研究があります。
また、商品として出ている物もあります。
今回の実装はセキュリティ的にアレゲな感じもしますが、勘弁して下さい。
手軽にパーソナルなクラウド
つながり感通信に関してもう一歩踏み込んでみます。
おうちハック的なプロジェクトは(そんな中から大当たりする物も出てくると信じていますが)、2014年現在は、デバイスやネットワークと使いこなす技術がこなれてきたことによって、多少なりとも技術が使える人が、個人の小さな満足を満たす仕組みを作りやすくなったことから発生している物が多いように思います。俗に言うMAKERSですね。
そういうパーソナルで小規模なサービスをIoTとしてネットワーク上で利用しようと思うと、気軽にクラウドのサーバを利用できることは非常に便利です。今回はさくらのVPSで運用していますが、heroku 的なものも便利だと思います。
実装の話 / さいごに
ざっくり言うと上の図に書いたようなシステムで動いているのですが、自分の技術まとめとして書きます。
ですが、今回は既に記事が長くなってしまっているので、次回に持ち越させてください。
Advent Calendar的にはこんな終わらせ方で良いのかな?? それではみなさん、メリークリスマス & 良いお年を~
UnityでOpenCVを どう使うか - OpenCVSharp vs OpenCV dllを使う環境 vs スタティックライブラリ
はじめに
最近何編かにわたって、Unityで OpenCV を使う方法についてまとめてきました。
扱った手法は大きく分けて三つあります
- OpenCVSharp を使う
- OpenCV のDLLを使う前提で、必要な関数をラップした Native Pluginを作る
- OpenCVの staticlib を必要な分だけ取り込んだ Native Plugin を作る
どの手法を使うか、ちょっと考えてみました
それぞれの特徴
1. OpenCVSharp
長所
- C# だけですんで楽
- DLLのビルドとかない
短所
- C++ の OpenCVに慣れているとちょいちょい混乱する。ちまたのリファレンスが基本 C++なだけに。
- C++ のライブラリを全部ぶっ込み、OpenCVSharp の DLLもぶっこみ、とする必要があるのでオーバーヘッド大。特に配布を考えると。
- あくまで有志の方が作った物で、公式の最新について行けるとは限らない
2. OpenCV のDLLを使う前提で、必要な関数をラップした Native Pluginを作る
長所
短所
3. OpenCVの staticlib を必要な分だけ取り込んだ Native Plugin を作る
長所
短所
- ビルドの設定が結構複雑
- デバッグが面倒
どう使うか?
こう考えました。
短所については
- ビルドの複雑さは慣れでカバー
というわけで、 3. staticlib を使ってDLLを作る が良いと考えました。
デバッグが面倒、という件も
- 一応前回の記事でクリアできたと思っている
- そもそもDLLにする主旨は、役割の分担を明確にし極力疎結合にすることです。データの受け渡しなど界面をしっかりと設計し、OpenCVで行う画像処理などは C++ 単体でテストしておいて、使えることを確認した後Unityで使うようにすべきでしょう。つまりデバッグは普通にC++で完結して行う。
という感じの進め方で良いと思っています。
(前回の記事)