2012年5月21日月曜日

xuggleのspeex_uwb_modeのリンクエラー対策

xuggleを利用して、iPhone用のライブストリーミング(フルスクリーンではない動作)をやりたいわけです。
iphone上でコメントの流れるながれる生放送を作りたいその1で書きましたが今回は・・・

音声:mp3ベースのm3u8ストリーミング
映像:jpgベースの画像をcanvasに書き込んでやりくりする。
この2本で攻めます。
これらのデータですが、xuggleとred5でやりくりで構築する予定です。

今回はこのxuggleのインストールで詰まった話。
インストールターゲットは、自分のPCであるMacOSX 10.6.8とサーバーとしてもっているサクラのVPS(CentOS)の2カ所です。

でやったことですが、http://www.xuggle.comから
https://github.com/xuggle/xuggle-xuggler/commits/master
こちらのgitのデータを入手。antでプログラムのコンパイルインストールを実行したのですが、speex_uwb_modeのリンクエラーがでました。動作しねぇ・・・

でいろいろすったもんだがあったあげく。
http://code.google.com/p/xuggle/
こちらのgoogle Code上にあがっているデータをCheckoutしてコンパイルしたら動作しました。
こちらでは問題なく動作しました。
リンクエラーで困った方は、google code側のデータも試してみてください。


さて、以下駄文。
今回xuggleを選んだ理由です。

・xuggleとred5は相性がいいです。過去にはxuggle-xuggler-red5というred5のストリームをリアルタイム変換するライブラリを公開されてました。これを利用すれば本当にリアルタイム画像縮小とかできて便利だし、リアルタイム画像データ加工とかもできます。
しかもパケットベースでデータにアクセスできます。

・一応rtmpdump(librtmp)とffmpegの組み合わせでもリアルタイム変換は実行可能ですが、次のような弱点があります。
1:放送ストリームがとぎれるとrtmpdumpがとまってしまう。
2:rtmpの仕様上、中途で映像を止めずに画質やコーデックデータを変更することが可能ですが、それを実行するとffmpegの動作が狂う(フレーム不正扱いになって動作しなくなる。)
3:rtmp上のflvでは、メディアストリームがシームレスであるという保証がない。
基本的にメディアデータにgapがあると動作がおかしくなってしまうのですが、データの構造上、間をあけて何秒から次のパケットを再生するということが可能になる。
またこの状態になったときにffmpegがきちんとすぐ動作する保証はない。

以上の点をふまえて次のような戦略でせめて見ます。
・音声データを始めからシームレスにつないだデータをリアルタイムに出力しつつ、音声の位置をベースに表示すべき画像を取得しそれで動画を作り上げる。
・音声データにgapがある場合は無音mp3のデータを挟むことで埋めてやる。(mp3の特性上キーフレームというのが存在しないので、プチっというノイズが入る可能性はあるがストリームが壊れることはないため、無音mp3は挟むたい放題です。長さは約0.2秒なのでうまくやれば人の気にならないくらいのずれに押さえることが可能。また、xuggleとred5の組み合わせでは1パケット情報ごとの管理ができるので、その点もgood)
・映像データはxuggle画像デコード時のVideoPictureをHookしてJavaのBufferedImageに変換。それをjpgにして出力することで準備する。

というやり方でせめる予定です。問題点であげたものに大しては
1:Red5サーバーへのパケット転送は放送プレーヤーが何しようが途切れることはない。
2:xuggle+red5で攻めた場合、コーデックデータ等が変わっても変換に利用する対象が1パケットの短いものなので影響はでない。仮にでても、そのパケットを捨てて次のパケットで復活させればOK
3:gapが仮にあっても無音mp3で埋めるので問題なし。
ということになります。

駄文その2
xuggle-xuggler-red5の簡単な解説。
xuggle-xuggler-red5では次のような手順で動作します。
1:Xuggle動作用のクラスの準備
Xuggleの動作用のIURLProtocolHandlerFactoryを拡張したRed5のパケット用クラスを準備する。Red5HandlerFactory.java
パケットを解析して送り出す。IURLProtocolHandlerを拡張したRed5用のクラスを準備する。Red5Handler.java
2:IBroadcastStreamのパケットデータを監視する。(red5の動作 IMediaStream.addStreamListenerで監視できます。)
受け取ったデータはqueueの形にして、コンバート待ちにする。
3:Transcoderという処理を実行するスレッドを立ち上げてそこでパケットにQueueがある限り変換を実行しまくる。
この部分に例では、listenerを仕込んで
変換前→デコード後→変換後の3カ所でデータに手がだせるようになっています。
4:変換後のパケットをRed5用のメッセージに戻してBroadcastStreamに流す(すると放送ストリームとして認識されて動作します。)
という一連の動作をものすごい早さで繰り返します。

今回の動作では、変換の目標をflv1への映像エンコードとmp3への音声エンコードを実行すると定義し、3のデコード後の画像を横取りしてjpg化、3の変換後の音声を横取りしてmp3化します。
ちなみにすでにjpg化と音声の内部データの確認は済んでいます。

駄文その3
xuggle-xugglerで作成されるライブラリの話。
xuggle-xugglerをコンパイルするとdistというディレクトリの中に動作用ライブラリ.soとかができ、さらにjava用のjarファイル等もできあがります。
僕の場合
[DLしたxuggle]/java/xuggle-xuggler/dist以下にできあがりました。
[DLしたxuggle]/java/xuggle-xuggler/dist/libにxuggle-xuggler.jarがあったわけですが、実はこれがコンパイルされたものではなかったという衝撃の事実が・・・
本体はなんと
[DLしたxuggle]/java/xuggle-xuggler/dist/stage/usr/local/share/java/jars/の中に別のxuggle-xuggler.jarが・・・
こちらをリンクしないとリンカーエラーがでるという事態に陥りました。
xuggleに手を出す方で、リンクがうまくいかないという場合は、PC内のどこにxuggle-xuggler.jarができているか再度確認したら幸せになれるかもしれません。


さて、あとはgapを埋めるロジックを考えて実際に動作するデモをつくるのみ・・・
いっちょやりますか。

0 件のコメント:

コメントを投稿