AS3とRed5で、flv録画環境を作る
USBのWebカメラで、Flash(AS3)のプログラムから動画を撮るやりかたを調べたのでメモ。
Flashによる動画撮影の流れ
Flashで作ったプログラムと、Flash Media Server(FMS)というサーバーソフトウェアを使うことになる。
- Flashによるプログラムが動画を撮る。
- 撮った動画をFMSに送信。
- FMSが、flvファイルとして(サーバー側に)保存。
こんな感じ。Flash自身には動画を保存する機能はなくて、サーバーに送ることしかできない。受け取ったサーバー側がflvファイルを保存することになる。
FMSは高いのでRed5
このFMS、すごく高い。何種類かあって、どれを買えばいいのかよくわかんないけど、どれもすごい高い(60万円とかする)。
そこでRed5。これはFMSのオープンソースの実装なんだそうだ。FMSがどんな機能を持っていて、そのうちどれだけの部分がRed5にも実装されているのかはよくわからないけど、とりあえずFlash側でWebカメラで撮った動画を保存する機能はあるっぽい。
すばらしいなあ。
Red5の動作確認
Windows版ならサービスとしてインストールされるので、管理ツールのサービスのところにある「Red5」というのを開始させればおk。これでサーバーが起動する。
起動にはちょっと時間がかかる(10〜20秒くらい?)ので慌てずに待つ。
ポート5080でWebサーバーが動き出すので、http://(IPアドレス):5080/ にアクセスすると、なんか以下のような赤いWebページが見えるはず。これが見えれば成功。そこにはデモアプリがたくさんあるので、見てみると面白いと思う。
デモを見る感じだと、動画関連に限らず、複数のブラウザで動くFlashを同期させる技術とかもRed5でやれるっぽい。面白そうだ。
Red5アプリケーションの作成
Flash側から送られてくる動画データを受け取ってflvファイルを出力するアプリケーションを作り、これをRed5で動かすようにする。
Red5自体はJavaで作られていて、Red5上で動かすアプリケーションもJavaで作る。ちなみにFMSはアプリをActionScriptで書くらしい。つまりFMSとRed5のサーバーサイドのアプリは互換していないわけか。Red5上に作ったアプリをFMSで動かしたり、その逆はできない。
で、JavaでRed5アプリを作る場合、普通にEclipseが使える。まあEclipseを使うっていうか、できあがったファイルをRed5のフォルダにコピーして動かすだけ。だからデバッガとかは使えないのかな?逆に言うと、別にEclipseとRed5を連携させたりするわけじゃないので(そういうEclipseプラグインもあるらしいけどまだ試してない)、EclipseじゃなくNetBeansでもテキストエディタでもなんでもいいと思う。多分。
アプリは作るけど、実装は空っぽ
通信で動画を受け取ってflvで書き込むアプリを書くということで、かなり大変そうだなあとか思ったけど、今回のような場合、アプリのURLさえあれば良い。動画を受け取ってflvで書き出す機能は標準で持っていて、要はFlashが接続してくるためのURLを準備してあげるだけでいいわけだ。
ってことで何もコードを書く必要は無かった。以下その手順。
- Eclipseで新しいJavaプロジェクトを作成。
- 自動で作られた src は不要なので消す。
- Red5インストールフォルダの doc/templates/myapp/WEB-INF をフォルダごとプロジェクト内に持ってくる。
- WEB-INF の下に、classes と src を作る。
- WEB-INF/src をソースフォルダーにして、WEB-INF/classes を出力フォルダにする。
- Add External JARs(外部JARの追加)でRed5インストールフォルダ直下の red5.jar の参照を追加。
- WEB-INF/src にパッケージをひとつ作って、Application クラスを作る(スーパークラスは org.red5.server.adapter.ApplicationAdapter にする)。実装は無くて良い(クラスの定義だけで良い)。
ここまでで以下のような感じになる。
各種設定
ここからさらに、設定ファイルをいじっていく。
WEB-INF/red5-web.properties
webapp.contextPath=/flvserver webapp.virtualHosts=*, localhost, 127.0.0.1
WEB-INF/red5-web.xml
bean要素(id="web.handler"のやつ)を以下のように。
<bean id="web.handler" class="com.nacookan.flvserver.Application" singleton="true" />
それから、bean要素(id="myhandler.service"のやつ)を削除。
WEB-INF/web.xml
まず、context-param要素(param-name要素が"log4jConfigLocation"のやつ)を削除。
そして、context-param要素(param-name要素が"webAppRootKey"のやつ)を以下のように編集。
<context-param> <param-name>webAppRootKey</param-name> <param-value>/flvserver</param-value> </context-param>
さらに、listener要素(listener-class要素がorg.springframework.web.util.Log4jConfigListenerのやつ)を削除。
あとservlet要素を削除。
最後にservlet-mapping要素を削除。
Red5への配置と再起動
Eclipseで WEB-INF フォルダを右クリックして、適当な場所にエクスポートする。それをRed5のインストールフォルダの下の webapps に flvserver というフォルダを作り、その中にコピー。
これで終わり。Red5を再起動(サービスの再起動)。
動作確認
とりあえずブラウザから http://(IPアドレス):5080/flvserver/ にアクセスして、以下のような Directory: /flvserver/ のシンプルな画面が出ればおk。
ここまでできれば、サーバー側は終わり。乙。
Flash側の開発
Flashがあればいいけど、無くてもテキストエディタだけでなんとかいける。
以下、全ソースコード。
WebCamRecorder.as
// WebCamRecorder.as package { import flash.display.*; import flash.events.*; import flash.media.*; import flash.net.*; public class WebCamRecorder extends Sprite { public function WebCamRecorder() { var nc:NetConnection = new NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{ if(e.info.code != 'NetConnection.Connect.Success') return; var cam:Camera = Camera.getCamera(); cam.setQuality(0, 80); cam.setMode(320, 240, 30, true); var mic:Microphone = Microphone.getMicrophone(); mic.rate = 44; var ns:NetStream = new NetStream(nc); ns.attachCamera(cam); ns.attachAudio(mic); ns.publish('video', 'record'); var v:Video = new Video(320, 240); v.attachCamera(cam); stage.addChild(v); stage.addEventListener(MouseEvent.CLICK, function(e:MouseEvent):void{ ns.close(); ns.attachCamera(null); ns.attachAudio(null); v.attachCamera(null); stage.removeChild(v); stage.removeEventListener(MouseEvent.CLICK, arguments.callee); }); }); nc.connect('rtmp://(IPアドレス)/flvserver'); } } }
以前書いたやり方でAS3の開発環境を作って、自分でコードをコンパイルしてswfを作る。
$ mxmlc WebCamRecorder.as
WebCamRecorder.swfが生成されれば成功。
使ってみる
WebCamRecorder.swf を起動すれば録画が始まって、映像の部分を適当にクリックすれば終了する。ちゃんと音も録音してるよ。
すると、サーバー側の webapps/flvserver/streams/video.flv が生成されているはず。これが今録画したビデオ。
撮った動画をストリーミングで見る
撮った動画を、サーバーからストリーミングで受けとって再生するFlashも作ってみた。
WebCamPlayback.as
//WebCamPlayback.as package { import flash.display.*; import flash.events.*; import flash.media.*; import flash.net.*; public class WebCamPlayback extends Sprite { public function WebCamPlayback() { var nc:NetConnection = new NetConnection(); nc.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{ if(e.info.code != 'NetConnection.Connect.Success') return; var ns:NetStream = new NetStream(nc); var v:Video = new Video(320, 240); v.attachNetStream(ns); v.smoothing = true; stage.addChild(v); ns.client = { onMetaData: function(o:Object):void{} }; ns.addEventListener(NetStatusEvent.NET_STATUS, function(e:NetStatusEvent):void{ if(e.info.code != 'NetStream.Play.Stop') return; ns.close(); v.attachNetStream(null); stage.removeChild(v); }); ns.play('video'); }); nc.connect('rtmp://(IPアドレス)/flvserver'); } } }
コンパイルは以下で。
$ mxmlc WebCamPlayback.as