kamaitachi によるマルチメディアサイトの構築
YAPC::Asia 2010 Tokyo
October 16th, 2010
kamaitachi とは
...
FMS とは?
...
FMS とは?
- Flash Media Server
- Flash Player 用のストリーミングサーバー
...
FMS とは?
- Flash Media Server
- Flash Player 用のストリーミングサーバー
- 独自プロトコル (RTMP)
FMS で何が出来るのか
...
FMS で何が出来るのか
- Flash Player との永続接続
- Remote Procedure Call (RPC, Remoting)
...
FMS で何が出来るのか
- Flash Player との永続接続
- Remote Procedure Call (RPC, Remoting)
- Video/Audio の送受信
...
FMS で何が出来るのか
- Flash Player との永続接続
- Remote Procedure Call (RPC, Remoting)
- Video/Audio の送受信
- 全部1TCPコネクションに混ぜることができる
いまさら FMS?
...
いまさら FMS?
- HTML5とかWeb Socketとかの時代?
- 忍者曰く…
...
いまさら FMS?
- HTML5とかWeb Socketとかの時代?
- 忍者曰く…
- 「10年後はkamaitachiとかなくなってそう(笑)」
2010年に FMS を使う理由
...
2010年に FMS を使う理由
- Webカムやマイクのサポート
- それ以外はHTML5などオープンな仕組みにシフトしていけばいい
FMSを使用している実際のサイト
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
- こえ部
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
- こえ部
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
- こえ部
- アメー○ピグ
...
FMSを使用している実際のサイト
- ustream, justin.tv, ニコニコ生放送
- こえ部
- アメー○ピグ
kamaitachi とは
- perl 製の FMS
- AnyEventベース (Danga::Socketから移行)
AnyEvent?
...
AnyEvent?
- 非同期アプリケーションを書くためのフレームワーク
- POEみたいなものだけど、POEよりきもくない
...
AnyEvent?
- 非同期アプリケーションを書くためのフレームワーク
- POEみたいなものだけど、POEよりきもくない
- くわしくは去年のmalaさんのスライドを参照のこと
AnyEvent - Danga::Socketとの違い
- Danga::Socket は epoll, kqueue, select のうすいラッパー
- AnyEvent はより多くのバックエンドに対応
- プログラミング方法自体はそんなに違いはない
AnyEvent - Danga::Socketとの違い
...
AnyEvent - Danga::Socketとの違い
...
AnyEvent - Danga::Socketとの違い
- ライブラリの充実度
- Danga::Socketのライブラリは実質Gearmanクライアントのみ (Gearman::Client::Async)
...
AnyEvent - Danga::Socketとの違い
- ライブラリの充実度
- Danga::Socketのライブラリは実質Gearmanクライアントのみ (Gearman::Client::Async)
- AnyEventは…
...
AnyEvent - Danga::Socketとの違い
- ライブラリの充実度
- Danga::Socketのライブラリは実質Gearmanクライアントのみ (Gearman::Client::Async)
- AnyEventは…
- AnyEvent::HTTP, AnyEvent::Gearman, AnyEvent::JSONRPC, AnyEvent::MPRPC, AnyEvent::XMPP, AnyEvent::IRC
...
AnyEvent - Danga::Socketとの違い
- ライブラリの充実度
- Danga::Socketのライブラリは実質Gearmanクライアントのみ (Gearman::Client::Async)
- AnyEventは…
- AnyEvent::HTTP, AnyEvent::Gearman, AnyEvent::JSONRPC, AnyEvent::MPRPC, AnyEvent::XMPP, AnyEvent::IRC
- and more 72 distributions on CPAN (2010-10-15現在)
kamaitachi 以外の選択肢
...
kamaitachi 以外の選択肢
- 本家FMS (ActionScript)
- wowza (ActionScript)
- red5 (Java)
...
kamaitachi 以外の選択肢
- 本家FMS (ActionScript)
- wowza (ActionScript)
- red5 (Java)
- kamaitachi (Perl!)
使い方
必要知識
...
必要知識
- 若干のAS3の知識
- 若干のRTMPの知識
- AnyEventでのコーディング手法
AS3
...
AS3
- 環境ないよ><
- ブラウザ上でFlashが作れるサービス「Wonderfl」
...
AS3
- 環境ないよ><
- ブラウザ上でFlashが作れるサービス「Wonderfl」
- http://wonderfl.net/
- 今回のデモは全てここに置きました
- ローカルでサーバー立ち上げてwonderflを開けば動きます
AS3
FMSへ接続
var nc:NetConnection = new NetConnection();
nc.addEventListener( ... ); // 各種イベント登録
nc.objectEncoding = ObjectEncoding.AMF0;
nc.connect("rtmp://example.com/app_name");
AS3
サーバー側の関数呼び出し
nc.call(
"method_name",
new Responder(resultCallback, errorCallback),
"foo", "bar"
);
AS3
サーバー側からの関数受付
nc.client = this;
public function onMessage(message:String):void {
// ...
}
AS3
Webカムからの映像を送信
var ns:NetStream = new NetStream(nc);
var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);
ns.publish("channel_name");
AS3
マイクからの音声を送信
var ns:NetStream = new NetStream(nc);
var var mic:Microphone = Microphone.getMicrophone();
ns.attachCamera(mic);
ns.publish("channel_name");
AS3
Webカムからの映像+マイクからの音声
var ns:NetStream = new NetStream(nc);
var camera:Camera = Camera.getCamera();
ns.attachCamera(camera);
var var mic:Microphone = Microphone.getMicrophone();
ns.attachCamera(mic);
ns.publish("channel_name");
AS3
FMSから映像、音声を再生
var ns:NetStream = new NetStream(nc);
ns.play("channel_name");
AS3との対応
// AS3
nc.connect(...)
// RTMP
connect
# kamaitachi
on_invoke_connect
AS3との対応
// AS3
ns = new NetStream(nc);
// RTMP
createStream
# kamaitachi
on_invoke_createStream
AS3との対応
// AS3
ns.publish(...)
// RTMP
publish
# kamaitachi
on_invoke_publish
AS3との対応
// AS3
ns.play(...)
// RTMP
play
# kamaitachi
on_invoke_play
AS3との対応
// AS3
ns.publish(...)
// RTMP
publish
# kamaitachi
on_invoke_publish
AS3との対応
// AS3
ns.close()
// RTMP
closeStream
# kamaitachi
on_invoke_closeStream
AS3との対応
// AS3
// NetStreamオブジェクトがガベージコレクトされたとき
// RTMP
deleteStream
# kamaitachi
on_invoke_deleteStream
kamaitachi アプリケーション
package MyApp;
use Any::Moose;
extends 'Kamaitachi::Service';
sub on_invoke_connect { ... }
sub on_invoke_play { ... }
:
kamaitachi アプリケーション
- RPC
- on_invoke_{メソッド名} がよばれる
- return したものが関数呼び出しの返値として返る
- レスポンスを遅延したいときは関数は単に return する
kamaitachi アプリケーション
sub on_invoke_sum {
my ($self, $session, $req) = @_;
my $res = $req->response(
undef, $req->args->[1] + $req->args->[2]);
return $res;
}
kamaitachi アプリケーション
sub on_invoke_sum {
my ($self, $session, $req) = @_;
my $t; $t = AnyEvent->timer(
after => 10,
cb => sub {
my $res = $req->response(...);
$session->io->write($res);
undef $t;
},
);
return;
}
kamaitachi アプリケーション
sub on_invoke_sum {
my ($self, $session, $req) = @_;
my $t; $t = AnyEvent->timer(
after => 10,
cb => sub {
my $res = $req->response(...);
$session->io->write($res);
undef $t;
},
);
return;
}
kamaitachi アプリケーション
- パケット受信時の関数
- on_packet_{パケットの種類} がよばれる
- 基本 on_packet_video, on_packet_audio だけしっておけばOK
kamaitachi 起動スクリプト
use Kamaitachi;
my $kamaitachi = Kamaitachi->new;
$kamaitachi->add_handler( port => 1935 );
$kamaitachi->register_services(
'application_name' => 'MyApp',
);
$kamaitachi->run;
kamaitachi 起動スクリプト
use Kamaitachi;
my $kamaitachi = Kamaitachi->new;
$kamaitachi->add_handler( port => 1935 );
$kamaitachi->register_services(
'application_name' => 'MyApp',
);
$kamaitachi->run;
kamaitachi 起動スクリプト
// AS3
nc.connect("rtmp://example.com/application_name");
定義済みサービス
- connect 処理とか毎回同じことをかくものが多い
- そう言う物をカプセル化した物
- with するだけで動作
定義済みサービス
package MyApp;
use Any::Moose;
extends 'Kamaitachi::Service';
with 'Kamaitachi::Service::AutoConnect';
# on_invoke_connect 定義済み
定義済みサービス一覧 (1)
- Kamaitachi::Service::AutoConnect
- Kamaitachi::Service::AutoConnectACL
- Kamaitachi::Service::Broadcaster
- つないでいるクライアント全員にパケットを送るための関数提供
定義済みサービス一覧 (2)
- Kamaitachi::Service::Recorder
- Kamaitachi::Service::Streaming
実行例
組み込みサンプルサーバー
$ git clone git://github.com/typester/kamaitachi.git
$ cd kamaitachi
$ git checkout anyevent
$ perl -Ilib ./example/server.pl
Job Worker との連携
- kamaitachi は非同期アプリケーション(AnyEvent)
- kamaitachi アプリケーション内部でブロッキングする処理をいれてはいけない
- そう言う場合はブロッキング処理は外部で行って結果を待つ
- AnyEvent::Gearman + Gearman
- AnyEvent::HTTP + HTTP (Web API)
Job Worker との連携実例
AnyEvent::Gearmanの場合
$gearman->add_task(
$function => $data,
on_complete => sub {
my $res = $_[1];
...
},
);
Job Worker との連携実例
AnyEvent::HTTPの場合
http_get "http://example.com/api/foo", sub {
my ($data, $headers) = @_;
...
};
Job Worker との連携実例
...
まとめ
...
まとめ
- kamaitachi は AnyEvent のおかげですごく拡張しやすくなった
...
まとめ
- kamaitachi は AnyEvent のおかげですごく拡張しやすくなった
- 難しいことをしなければサーバーサイドはexampleをそのまま使うだけでサイト出来ちゃう
...
まとめ
- kamaitachi は AnyEvent のおかげですごく拡張しやすくなった
- 難しいことをしなければサーバーサイドはexampleをそのまま使うだけでサイト出来ちゃう
- 難しいことをしようとするとRMTPの知識が必要
...
まとめ
- kamaitachi は AnyEvent のおかげですごく拡張しやすくなった
- 難しいことをしなければサーバーサイドはexampleをそのまま使うだけでサイト出来ちゃう
- 難しいことをしようとするとRMTPの知識が必要
宣伝
...
宣伝
- 面白法人カヤックはエンジニアを募集しております!
- 鎌倉移住キャンペーン中!
...
宣伝
- 面白法人カヤックはエンジニアを募集しております!
- 鎌倉移住キャンペーン中!
- 求めている人材リアルタイム速報
ご静聴ありがとうございました!