少し前にTwitterでARビデオ名刺を作るぜ!とか言ったまま何もアウトプットを出してないが、実は動作確認レベルはすぐに出来た。内容はといえば、以前作ったURL入力版のARメタセコビューワとほぼ同様で、動画(flv形式)のURLを入力してOKを押すと、以降マーカ上で動画が再生されるというもの。
で、結論としては、ただ再生させるだけなら簡単だというもの。チョロッとしたサンプルとしてなら公開してもいいんだが、残念ながら俺には手持ちの動画が無かったのでちょっと停滞中。テストではYouTubeとかニコニコ動画からDLしてきた動画を使ったんだが、さすがにそれを流用というわけにも行くまいし。
何か方法を考えて公開しいたいとは思うが、わざわざ動画を作るのが面倒な気も・・・何とかします。
実装について
2通りの方法で作ってみた。
- Papervision3Dの「
VideoStreamMaterial
」を使う方法 - SandyのDistortImgをAS3用に移植したものを使う方法
どちらにも共通する問題点があって、カメラに沢山のものが映っていると、音声がブツ切れになってしまう。例えば、部屋の様子を広く映し、マーカは結構引いてて小さめという状況だとかなりヤバい。
この、俺のお気に入り曲「ニラ」で試した結果、扇風機越しか!?という感じになってしまった。
ただし、カメラに映ってるのがほぼマーカだけという状況であれば、問題なく再生されるようだ。
あと、あんまり音が流れないものだと、この問題に気付かれない(元々こんなモンかな?と思われる)ので大丈夫かもしれない。
VideoStreamMaterialの問題点
VideoStreamMaterialを使う方法だと、Papervision3Dの技術を生かし、3Dオブジェクト上に動画を出すので、俺が以前に作ったサンプル「SimpleFLARToolKitView」をそのまま流用できるという利点がある。
ということでまず、VideoStreamMaterialを使って試したんだが、コイツが結構危険な代物で、動画を再生する前にnew
してしまうと、デバッグ用のFlash Playerや、なんならブラウザまで一撃死させるという凄い落ち方をする。
例えば、以下にVideoStreamMaterialを使うサンプルコードを示す。
- package
- {
- import flash.events.Event;
- import flash.events.NetStatusEvent;
- import flash.media.Video;
- import flash.net.NetConnection;
- import flash.net.NetStream;
- import org.papervision3d.materials.VideoStreamMaterial;
- import org.papervision3d.objects.primitives.Plane;
- import org.papervision3d.view.BasicView;
- public class VideoStreamMaterialSample extends BasicView
- {
- private var _plane:Plane;
- private var _connection:NetConnection;
- private var _stream:NetStream;
- private var _video:Video;
- public function VideoStreamMaterialSample()
- {
- super(640, 480, true, true);
- this.camera.z = -100;
- this._connection = new NetConnection();
- this._connection.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
- this._connection.connect(null);
- }
- private function onNetStatus(e:NetStatusEvent):void
- {
- if (e.info.code == "NetConnection.Connect.Success" )
- {
- this._stream = new NetStream(this._connection);
- this._stream.client = { };
- this._video = new Video();
- this._video.attachNetStream(this._stream);
- /* (1) */this._stream.play("sample.flv");
- /* (2) */var vsm:VideoStreamMaterial = new VideoStreamMaterial(this._video, this._stream);
- vsm.doubleSided = true;
- this._plane = new Plane(vsm, 320, 240);
- this.scene.addChild(this._plane);
- this.addEventListener(Event.ENTER_FRAME, onEnterFrame);
- this.startRendering();
- }
- }
- private function onEnterFrame(e:Event):void
- {
- if (this._plane) {
- this._plane.rotationX += 5;
- }
- }
- }
- }
「sample.flv
」は適当な動画に変えて試して欲しいんだが、コード中の(1)と(2)の順番を入れ替えただけで、以下のようになってしまう。
Firefoxで試しても、似たような運命を辿っていた。あと、画面の歪みがキツイのが最大の弱点だ。
DistortImage
と言うわけで、VideoStreamMaterialは怖いし歪む。そこで次にDistortImageを使ってみた。これは元々SandyというライブラリのAS2版に入っている、画像を歪め手表示するクラスで、それをAS3に移植した方がおられたので、それを利用してみたというわけだ。DistortImageならば変形時の分割数を指定できるので、歪みが少なくて済む。
て言うか、探していたら先人が見つかった。
Flexで有機ELの薄さなんて目じゃない厚さが紙のTVを作成しました。
動作ムービーはこちら
http://jp.youtube.com/watch?v=oczVc3YbN-w
PHP,MySQL,Flexな日々+イラストとか
この人はFLARToolKit以外の方法で動画の描画位置を検出してるけど、原理的には同じだ。DistortImageを使うには、動画の4つの角になる部分を見つけ出せばよい。実際にはこんな感じ。
//DistortImageオブジェクトの初期化
this._distort = new DistortImage(320, 240, 4, 4);
・・・
//Webカメラの映像をマーカ探索用BitmapDataに描画
this._capture.bitmapData.draw(this._video);
//表示する動画を変形用BitmapDataに描画
this._movieBD.draw(this._movie);
//前フレームで表示していた動画を消去
this._movieCanvas.graphics.clear();
//マーカ探索を実行。見つかった場合trueが返される
if (this._detector.detectMarkerLite(this._raster, 80)) {
//見つかったマーカの正方形情報を取得
var square:FLARSquare = this._detector.getSquare();
//マーカ内の頂点情報(2次元配列)を、DistortImageが扱えるPointに変換
var points:Array = new Array();
for (var i:uint = 0; i < 4; i++) {
points.push(new Point(square.sqvertex[i][0], square.sqvertex[i][1]));
}
//DistortImageによる変換の実施
this._distort.setTransform(this._movieCanvas.graphics,
this._movieBD,
points[0], points[1], points[2], points[3]);
[/as]
これをEvent.ENTER_FRAME
のイベントハンドラとして実行すると、動画がマーカ上に表示される。ただし、これだと向きがおかしいので、ポイントの順番をずらす必要があるが。
この後どうするか
取り敢えず、何か動画を作ってサンプルを公開したい。で、その際には再生・停止・リピートくらいは付けたい。リピートは自動でなくても、再生終了を検知→再生ボタンが使用可能になるみたいなのでもOK。あと、必須なのがマーカが消えたら一時停止する機能。これが無いとわざわざARにする意味が無い。
扇風機越しみたいになる問題についても、「取得されたマーカの四角形が、全体の80%以上の時だけ認識成功とする」とか制限を付ければいいんじゃないかな?要するに扇風機状態になる頃には動画が止まっててばれないという凄い作戦だが。
ちなみに、サンプルに使える動画募集中です。