red5を使ってライブストリーミングアプリケーションをつくる

red5というjavaで書かれたオープンソースのストリーミングサーバがあるんですが
先週の火曜日にふと思い付いてプライベートなニコニコ生放送を作りました。

現代はライブストリーミングアプリケーションまでフリーのライブラリだけでいけちゃうというのに驚きましたね。


とりあえずred5をダウンロードしてきます。最新版はGoogleCodeにありますね。
自分はRed5 0.9.1 FinalのZIPを落としてubuntuで起動してみました。
解凍したディレクトリに移動して

$sh red5.sh

で起動します。

とりあえず最初からは入ってるデモを実行してみましょう。
http://localhost:5080
にアクセスするとデモのトップページがでてくるので
Launch a demo
をクリックして適当なデモを見てみます
とりあえず一番上のShared Ballを見てみましょう

デモに利用するプロジェクトをインストールする必要があるので
上に書かれている
rtmp://localhost/SOSample
を先ほどのtopの「You must install the demo applications before running them. 」のリンクからデモ用のパッケージをインストールします。
それで先ほどのShared BallのページでURLの下にある斜めの棒みたいなボタンをおすとred5にコネクションを張り、他のブラウザで開いたデモとボールの位置が同期されて動きます。

こんなかんじでチャットやら動画のストリーミング、ライブストリーミングのデモがすでに用意されているのでそれを参考に作っていきました。
red5のサーバ側の設定はここにあるoflaDemo/を参考にします。
とりあえずeclipseを起動してjavaプロジェクトを作成します。
次にsrcフォルダとWEB-INFフォルダを作成。
WEB-INFフォルダ以下にclassesフォルダ、srcフォルダを作成します。あとred5-web.propertiesとred5-web.xmlとweb.xmlも必要です。
こんなかんじです。

あとビルド・パスの設定なんですが
ソースフォルダの追加で先ほど作成したWEB-INF以下のsrcを追加、Default output folderでWEB-INF以下のclasssesを設定します。
つぎにライブラリにred5.jar(たぶん解凍したフォルダ直下にある)を追加します。

つぎにsrc以下に好きなようにパッケージを作成して根幹となるApplication.javaを作成します。
Application.javaはまぁ名前はなんでもいいんですけどApplicationAdapterを継承してください。
これでソースの記述は終了です。いろいろ拡張したい場合は@overrideでいろいろ書いていきます。今回ははぶきます。

で先ほどの意味不明なred5-web.propertiesとred5-web.xmlとweb.xmlたちなのですが、ここにきてちゃんと書きます。
作成したjavaプロジェクトはred5/webapp/以下においてsh red5.shすれば動くのですが、そのディレクトリに先ほど上でインストールしたSOSampleというフォルダがあるのでそこのWEB-INF以下にあるred5-web.propertiesとred5-web.xmlとweb.xmlをコピりましょう。

red5-web.properties

webapp.contextPath=/SOSample

となっているのを自分の作成したプロジェクト名に変更

red5-web.xml

<bean id="web.handler" class="org.red5.server.adapter.ApplicationAdapter"/>

を自分の環境に合わせましょう
src以下のパッケージがcom.hoge.fubaにApplication.javaを作成してたら

class="com.hoge.fuba.Application"

となります

web.xml

<param-name>webAppRootKey</param-name>
<param-value>/SOSample</param-value> 

のSOSampleを自分のプロジェクト名に変更。

これでサーバ側の設定はおわりです。プロジェクトごとred5以下のwebappフォルダにぶち込んで再起動すると走り出します!!
ちなみにここまで書いといてなんですがeclipseにはred5用のプラグインがあるらしいです。簡単にred5プロジェクトが作れるらしいので是非。


つぎにストリーミングデータ送信側と再生するflashのほうに生きたいと思います。
flashの方はactionscriptのライブラリでNetConnection,NetStream,SharedObjectというのが用意されているので非常に簡単にできます。

flash側はflash builder 4の体験版使ってやります。学生は申請すれば無料で使えたような気がします。こんど申請してみます。

private var nc:NetConnection; //rtmpサーバとコネクションを張る
private var ns:NetStream; //ストリーミング映像を配信する
private var so:SharedObject; //クライアント同士で共有するオブジェクト

private var camera:Camera;
private var mic:Microphone;

private function init():void{
    camera = Camera.getCamera();
    if(camera){
        var video:Video = new Video(camera.width, camera.height);
        video.attachCamera(camera);
        display.addChild(video); //表示したい場所にaddする

        if(nc == null){
            nc = new NetConnection();
            nc.objectEncoding = ObjectEncoding.AMF0;
            nc.connect("rtmp://127.0.0.1/プロジェクト名");
            nc.addEventListener(NetStatusEvent.NET_STATUS, onNetStatus);
            nc.addEventListener(SecurityErrorEvent.SECURITY_ERROR, onSecurityError);
        }
    }
}

private function onNetStatus(evt:NetStatusEvent):void{
    switch(evt.info.code){
        case "NetConnection.Connect.Success":
            initSO();
            initNS();
            break;
        //ほかのも書いてく
    }
}
private function onSecurityError(evt:SecurityErrorEvent):void{
    trace("SecurityError");
}
private function initSO();void{
    so = SharedObject.getRemote("comment", nc.uri, true); //ここの"comment"という名前でサーバ側が処理するSharedObjectを認識しているのでチャンネルごとにコメントを分けたい場合はチャンネルごとにcomment1やcommnet2などに変える
    if(so){
        so.addEventListener(SyncEvent.SYNC, function(evt:SyncEvent):void{
            //コメントが新しく追加されたら動画の上を流れるようにする
            if(so.data.comment != undefined) flowComment(so.data.comment);
        });
        so.connect(nc);
    }
}
private function initNS():void{
    ns = new NetStream(nc);
    ns.attachCamera(camera);
    ns.attachAudio(mic);
    ns.publish("hogeBroadcast", "live"); //ここの"hogeBroadcast"も名前を変えるとチェンネルごとのストリーミング内容になる。このライブストリーミング映像を受信したい場合はns.play("hogeBroadcast", -1);とする
    //ちなみに"Live"を"Record"にすると録画になる。
}
private function flowComment(var comment:String):void{
    //以下略
}

ちなみにプライベートニコニコ生放送はセキュリティーのためにflash側からコネクションをはるときにパラメータでユーザ名とハッシュ値red5側に渡して、正規ユーザとしかコネクションをはれないようにしています。そういったred5のサーバサイドなどの話はまた後ほどということで
実際の画面↓

書いてる途中で飽きてきてactionscript側のコードとかてきとうすぎる感じになってしまいました...
まぁ先行者は結構いるのでそちらの方々のソースを参考にするか公式にもいろいろ置いてあるのでそちらを参考にしたほうがいいですね...

日本語のページだと http://coelacanth.heteml.jp/site/flash_red5/index とかが参考になりました。