お正月なのでUstreamをGoogle マップ上に表示してみた

by key

あけましておめでとうございます。

おかげさまでBOWは新しい年を迎えることができました。本年もよろしくお願いいたします。

さて、僕はお正月にUstreamで色々遊んでたんですが、こんなものができましたのでブログに書いてみます。

UstreamMap

UstreamMap

これは何?

UstreamのData APIを使って最新のストリームを取得し、それらのうちGPS情報が取得できるものだけをGoogle マップ上に表示してます。

眺めているだけでも楽しいですが、Ustream Live Broadcasterを使ってマップ上に参加することもできます。これを使って色々面白い遊びができそうです。

何で作った?

大晦日に、Ustreamの新着をTwitterから拾って並べるものを作ったのですが

ustreeeeam (重いです)

これを元日に見てたところ、

じゃあ地図上に並べようということになったのでした。

遊び方

眺めて遊びます。誰かが位置情報を有効にした状態でUstreamを始めると、しばらくして地図上に現れます。(Ustreamの混雑状況や同時閲覧者数により、出るのに時間がかかったり、取りこぼしたりするかもしれないです)

気になるストリームを見つけたら、Ustreamロゴを押せばチャンネルページへ飛べます。

iPhoneのUstream Live Broadcasterを使う場合は、設定でSend locationを”Always”ではなく”Ask on startup”にしないと位置情報が有効にならないかも?という報告がありました。(検証中)

仕組み

位置情報を提供しているWebサービスとGoogle マップを組み合わせるのはマッシュアップの初歩の初歩ではありますが、今回はちょっと苦労しました。

大まかな動作の流れは以下のようになっています。

  1. Ustream Data APIを使って新着ストリームを取得
  2. Flashで順番に開いていき、位置情報を含むストリームを抜き出し
  3. その位置情報をGoogle マップに渡してマップ上に表示してもらう

ここで苦労したのは

  • GPSに対応してるストリームがあんまり無い
  • GPSに対応してるか調べるのが面倒
  • ストリームの入れ替わりが激しい

という点でした。

GPSに対応してるストリームだけを集めるには

結論から言うと、Ustream Runtime Shared Libraryを使って総当りで調べる方法以外見つけていません。

最初のうちは「位置情報が使えるのはiPhoneなのだから、iPhoneからの配信だけ取得すれば良いのでは」と考えてTwitter検索から取得しようとしてみましたが、意外と位置情報オフで使ってるユーザが多く、S/N比の向上はイマイチです。

そこで中途半端なフィルタリングは諦め、Ustream Data APIを使って新鮮なデータを自前で捌くことにしました。

新鮮なストリームの入手方法

Ustream Data APIでライブ中のストリームを得るには

  1. liveスコープを使う方法
    http://api.ustream.tv/html/channel/live/search/all
  2. streamサブジェクトエリアを使う方法
    http://api.ustream.tv/html/stream/recent/search/all

があり、ドキュメントでも比較が載っています。が分かりにくいので解説すると、まずこれらのAPIが検索する対象はchannelとstreamの違いがあります。

Ustreamを視聴してると経験があると思いますが、チャンネルページを開いていると放送が始まって、ブツッと切れて、放っておくとまたオンエアになったりします。これが「1つのチャンネルを見ていたら2つのストリームを受信した」状態です。二者の違いが分かりやすいのではないでしょうか。

前者のAPIは、channelサブジェクトのうちlive状態であるもの、つまりstreamが入っている状態のものを返します。このliveを指定することでオンエアの結果だけを得ることができます。

後者のAPIは、streamサブジェクトを新着ソートして返します。オフエア状態が存在するchannelと違い、streamの検索結果は全てオンエア状態です。(と言うのも変ですが)

imageUrlなど一部の情報はchannelを調べないと得られませんが、今回は必要ないので、新着ソートできる後者のAPIを使いました。

結果のフォーマットは、htmlの部分をxmlとかjsonとかに変更できます。

またDevelopperKeyを付加して呼び出す必要があります。詳しくはドキュメントを見てください。

ちなみに、Twitterを使ったストリームの入手方法

ustre.amで検索するとたくさん引っかかります。

HTML埋め込みやFlashで再生するにはcidを取得する必要がありますが、(もちろん上記URLをスクレイピングしても良いのですが)もっと簡単な方法があります。

ustre.am/ に続く3~4桁の英数字は単なるcidの62進数表記なので、簡単な計算式で相互変換できます。

簡単なコードを書いておきますね。

  1. private static const table:String = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
  2. public static function getUrlFromCid(cid:uint):String {
  3.     var url:String = "";
  4.     while (cid) {
  5.         url = table.charAt(cid % 62) + url;
  6.         cid /= 62;
  7.     }
  8.     return "http://ustre.am/" + url;
  9. }
  10. public static function getCidFromUrl(url:String):uint {
  11.     var id:String = url.split("/").pop();
  12.     var cid:uint = 0;
  13.     for (var i:int=0; i<id.length; i++) {
  14.         cid += table.indexOf(id.charAt(i)) * Math.pow(62, id.length - i - 1);
  15.     }
  16.     return cid;
  17. }

ストリームが位置情報に対応しているか調べるには

Ustream Runtime Shared Libraryを使いました。

基本的な使い方はFlash : Ustream Flash Client APIを使ってみる - SWFなカスタムパネルで中継を再生が参考になりました。

位置情報を取得するには、

  1. logicを作る(上記参照)
  2. logicの”createChannel”イベントを見張る
  3. logic.channelにアクセスできるようになるので取っておく
  4. channelの”online”イベントを見張る
  5. channel.modulesにアクセスできるようになるので取っておく
  6. modulesの”createGps”イベントを見張る
  7. modules.gpsにアクセスできるようになるので取っておく
  8. gpsの”update”イベントを見張る
  9. gpsのcountry, city, latitude, longitude, altitudeが取得できる

という手順になります。

ただしこのままでは「位置情報に対応していない」というゴールが無いので、適切なタイムアウトを設けてやります。僕の環境では平均して600ミリ秒ぐらいで位置情報に辿り着けましたが、ストリーミングを複数同時に見るというアプリケーションの性質上、十分な余裕を見て2000ミリ秒に設定しています。

余談

上記GPSクラスのASDoc

Event
(空欄)
Summary
Fires when the gps informations are available.

って書いてあって絶望しました。

でたらめに色々入れてみてdataだと分かりましたが。

常にストリームが表示されるようにするには

Ustreamから大量のストリームを取得する方法と、そこから位置情報つきストリームを選別する方法は分かりました。

しかし、実際に組み合わせてみると、なかなか位置情報つきストリームに出会えません。作って間もないので統計を取っていないので僕の感覚なのですが、位置情報を有効にしているストリームは全体の1~2%程度しかいないようです。

1つ解析するのに2秒かかるシステムでは厳しそうなので、サーバ側にデータベースを用意することで、各ストリームの解析済み状態・位置情報・オンエア状態の管理を行うことにしました。

  1. まずサーバ側プログラムがData APIを使って新着ストリームを100件受信します。それらはDB上の「未解析リスト」に加えられます。
  2. Flashクライアントがサーバから「未解析リスト」のうち10件を受け取ります。
  3. Flashクライアントは2秒に一つ、上記リストを処理し、「位置情報の有無」「オフエアになったか」を報告します。
  4. サーバは結果を受け取り、オフエアの場合はDBから削除し、そうでない場合は「位置情報有りリスト」か「位置情報無しリスト」に分類します。
  5. Flashクライアントがサーバから「未解析リスト」のうち新しい10件を受け取ります。また、「位置情報有り」リストがあればそれも受け取ります。

という仕組みのおかげで、ページを開いてすぐに位置情報有りのストリームが再生できるようになりました。

実際にはもう少し複雑で、

  • Data APIから再び取得した際に「位置情報無しリスト」にあるものは無視する
  • ただし一旦途切れて別のストリームになっていた場合(放送開始時間が新しい場合)は再度「未解析リスト」に戻す
  • Flashクライアントが複数同時に起動した際に効率良くストリームをチェックできるように、未解析リストから各自に別々のストリームを渡す。

などの工夫も入れています。

制作時間

1/6と1/7の深夜に6時間ずつぐらい。

感想

新年から楽しいものを作れて嬉しいです。今年はこういうアウトプットを増やしていきたい。

と言うわけで、今年もよろしくお願いします。

タグ: ,

コメント / トラックバック 1 件

  1. GoogleMap上に配信中のUstreamを表示するサービス「UstreamMap」 | Web活メモ帳 より:

    [...] pekolog» ブログアーカイブ » お正月なのでUstreamをGoogle マップ上に表示してみた [...]

コメントをどうぞ