はてなブックマーク - USTREAM Flash Client APIの使い方
    このエントリーをはてなブックマークに追加

    はじめまして、Fusicの杉本です。

    Fusic Advent Calenderのルーレットをノリで作った張本人です。
    ここまで同じ人に複数回当たったり、言い出しっぺの弊社小山が当たっていなかったりと、バグって偏っているのではと責められてきましたが、やっと自分が当たって疑いが晴れた感じです。

    USTREAM API

    USTREAMといえば、先日宇多田ヒカルさんのライブを中継して話題になりましたね。
    同時アクセス10万以上、ユニークユーザ34万5000人、加えてあの画質と音質、USTREAMすごい!と感動した方も少なくないのではないでしょうか。
    また弊社でもUSTREAMを使ったサービスZENPREを提供しています。ご存じない方は是非一度アクセスしてみて下さい。

    さて、USTREAM APIの情報については、こちらに公開されています。

    • Data API Documentationは、ユーザ情報やチャンネルのURL、タイトル、概要などをhtml/json/xml/php形式で返してくれるAPI情報です。
    • Flash Client API Documentation (AsDoc)は、LIVE動画や録画動画のビューワや動画配信するブロードキャスターのFlashをカスタム実装するためのAPI情報です。

    今回はUSTREAMのFlash Client APIについて、ご紹介したいと思います。

    Flash Client API

    ドキュメントはASDoc形式になっていて見慣れた感じですが、コメントが少なく非常に分かりづらいです。
    実装の仕方はここにサンプルなどがあります。ここではビューワの実装方法について説明していきます。
    まずは提供されているswfをロードします。

    Security.allowDomain("*");
    var viewerLoader = new Loader();
    viewerLoader.contentLoaderInfo.addEventListener(Event.COMPLETE, onRslLoad);
    this.addChild(viewerLoader);
     
    var applicationDomain:ApplicationDomain = ApplicationDomain.currentDomain;
    var loaderContext:LoaderContext = new LoaderContext();
    var request:URLRequest = new URLRequest("http://www.ustream.tv/flash/viewer.rsl.swf");
     
    loaderContext.applicationDomain = applicationDomain;
    viewerLoader.load(request, loaderContext);

    LoaderのCOMPLETEイベントでtv.ustream.viewer.logicパッケージのLogicクラスをインスタンス化します。

    private function onRslLoad(e:Event):void {
    	var logicClass:Class = viewerLoader.contentLoaderInfo.applicationDomain.getDefinition("tv.ustream.viewer.logic.Logic") as Class;
    	viewer = new logicClass();
    }

    Display Class

    表示するUSTREAM映像の大きさを指定します。上記viewerオブジェクトのdisplayプロパティで値を設定します。width=300,heigth=200くらいが最小値のようです。

    viewer.display.width = 360;
    viewer.display.height = 240;

    Channel ClassとRecorded Class

    チャンネルの設定や動画の再生・停止、音量調整などはこちらのクラスを使います。
    Channel ClassがLIVE配信用、Recorded Classが録画再生用となっています。基本的に使い方は同じですが、動画をロードするメソッドが異なります。

    // LIVE配信用のロード
    viewer.createChannel(channelId);
    // 録画用のロード
    viewer.createRecorded(channelId);

    channelIdが少し分かりづらいですが、以下のようになっています。
    LIVE配信用は、ライブ配信ページのURL「http://www.ustream.tv/broadcaster/*******」の一番最後のスラッシュ以下の数字
    録画再生用は、録画動画受信ページのURL「http://www.ustream.tv/recorded/*******」の一番最後のスラッシュ以下の数
    となっています。このメソッドをたたくと、USTREAMにchannelIdを渡して、動画を読み込み始めます。
    余談ですが、サービスでこのchannelIdをユーザに入力してもらうのは難しいと思いますので、今回は紹介していないUSTREAMのData APIと連携し、番組名の登録でchannelIdを取得するようにしてみてはいかがでしょうか。(ZENPREではそうしています)

    イベント

    次に、その際に発生するイベントについて発生する順番で説明をしていきます。

    • found・・・指定したchannelIdの動画が見つかった時
    • video・・・ビデオが見つかった時
    • audio・・・音声が見つかった時
    • createStream・・・動画ストリームがつながった時
    • getProgressive・・・動画のダウンロードが開始した時
    • progress・・・動画のバッファを読み込む毎に

    その他のイベントについても簡単に説明をします。

    • finish・・・動画が最後まで再生された時
    • destroy・・・インスタンスを削除(destroyメソッドを叩いた)した時
    • muted・・・ミュートした時

    これらイベントは、LIVE配信時と録画再生時では参照するプロパティが異なりますので、注意して下さい。以下に例を示します。

    // LIVE配信時
    viewer.channel.addEventListener("found", function(e:Event):void {
    				// 処理を入れる
    });
    // 録画再生時
    viewer.recorded.addEventListener("found", function(e:Event):void {
    				// 処理を入れる
    });

    動画の再生・停止のイベントがないのがちょっと不便です。これらは自前で実装する必要があります。

    主要なメソッドとプロパティ

    最後にプレーヤを実装する上で注意が必要なメソッドとプロパティを説明をします。

    【メソッド】

    • seek(percent:Number, bufferOnly:Boolean = false):Boolean

    →シーク先の値は、録画動画のトータル再生時間における割合(値は0以上1以下)を第1引数に渡します。後述のプロパティdurationを使って算出します。

    【プロパティ】

    • bufferProgress: Number[読み取り専用]

    →動画データのダウンロードしたバッファーのプログレス値。値は0以上1以下です。

    • duration: Number[読み取り専用]

    →動画のトータル再生時間。単位は秒。

    • seekTo: Number[読み書き込み]

    →seekメソッドと同じ。こちらも値は録画動画のトータル再生時間における割合(値は0以上1以下)のため注意。

    • time: Number[読み取り専用]

    →現在の動画再生時間。単位は秒。

    • volume: Number[読み書き込み]

    →動画の音量。値は0以上1以下です。

    まとめ

    以上、USTREAM Flash Client APIの使い方の紹介でした。
    紹介した以外にも色々なAPIが用意されていますので、興味のある方は是非カスタムプレーヤを作ってみて下さい。またLIVE配信をする時は、通常USTREAMが用意したFlash(Web)かProducerを使うと思いますが、このAPIを使うと自前でブロードキャスタも作れます。

    今年Ustream Asia Inc.も設立され、ストリーム配信が盛り上がってきています。TVやラジオといったメディアの形が見直され、いつでもどこでも誰でも簡単に配信できる環境ができてきています。
    いままで当たり前だったことが崩され、変化していくというのはおもしろいですよね。自分が持っているものでコンテンツ化できるものがないか考えてみると、新しいサービスやビジネスが思いつくかもしれません。その第一歩として、弊社サービスZENPREを使ってみるのはいかがでしょうか。
    と、宣伝をいたしまして終わりたいと思います。
    (私は社内一まじめな人間なので、他の人みたいにボケたり、オチを入れたりしません。)

    長文を最後までお読みいただき、ありがとうございました。
    それでは良いお年を(もう当たらんだろう)

      はてなブックマーク - [rails] config.cache_classes = trueでも特定のクラスだけアクセスの度にloadする
      このエントリーをはてなブックマークに追加

      Ruby技術者認定試験に合格してほっとして倒れそうな山本ですこんにちは。

      (Rails2.xの話になります)
      さて、Railsでは起動時に環境の指定ができますが、productionモードの時はある程度のクラスがキャッシュ化されて読み込みが早くなります。
      通常であれば、config/environments/production.rbに以下の記述があると思います。

      config.cache_classes = true

      これにより、クラスは起動時の一回のみの読み込みとなり高速化が図られてます。

      話はちょっと変わりますが、modelクラスでバリデーションを定義するとき、メッセージを個別に指定したい場合は以下のように書くと思います。

      validates_format_of :hoge, :with => /moge/,  :message => "mogeと書いてください。"

      この時、以下のように

      validates_format_of :hoge, :with => /moge/,  :message => "(#{Time.now}に発生)mogeと書いてください。"

      にして、クラスが読まれたときの時間を表示するといった場合、
      developmentモードでは、その時の時間が表示されるのですが、productionモードでは初回の起動時の時間が表示されたまま、変わることはありません。
      これはproductionモードだとmodelクラスが一度しか読まれないからです。

      そもそも、productionモードでは何が起こっているのか

      ひとえにproductionモードと言っても、ウラでは何が起きているのか。
      その情報を見つけることができなかったため、ソースを追ってみました。

      config.cache_classesは、どこで何らかの処理をされているのか。
      config/environments~以下の各クラスで定義されている、
      config.cache_classesは、どこで判定がされ処理されているのでしょうか、ってことで探してみると以下の場所にありました。

      # Rails2.3.5 rails-2.3.5/lib/initializer.rb
      def initialize_dependency_mechanism
        ActiveSupport::Dependencies.mechanism = configuration.cache_classes ? :require : :load
      end

      ここで、クラスを読み込むために、requireを使うかloadを使うかのか判定を行っています。
      requireは一度しか読み込みませんが、loadは何回でも読みます。

      特定のクラスだけ読み込む術はないものか

      “指定したクラスだけは、load読み込みにする” なんてのができればいいのでしょうが、一括で起動時にrequireしてしまっているので、どうしようもないのかなとか思いつつ、いろいろやってみました。
      ActiveSupportのDependenciesクラスが色々と鍵を握ってるみたいです。

      まず、controllerにbefore_filterを仕込みその中で、以下のように書いてみました。

      ActiveSupport::Dependencies.load_file("Modelクラスへのパス")

      いかにもなメソッドです。loadし直してくれるのではと、やってみましたが表示時間は変わらず結果は×。

      次に、

      ActiveSupport::Dependencies.load_with_new_constant_marking("Modelクラスへのパス")

      これもいかにもな名前です。が、あえなく×。

      で、

      modelクラスに "unloadable" と宣言する

      ついに見つけました! これを書けば起動時にこのクラスが読まれることはない! はず!

      と意気揚々と試しましたが、×。

      こうなったらと、手当たり次第作戦。
      すると、以下のメソッドをbefore_filterに仕込むと、アクセスの度に、表示する時間が変わりました。

      ActiveSupport::Dependencies.remove_unloadable_constants!

      ついにやったと思いつつ、ソースを見てみます。

      def remove_unloadable_constants!
        autoloaded_constants.each { |const| remove_constant const }
        autoloaded_constants.clear
        explicitly_unloadable_constants.each { |const| remove_constant const }
      end

      どうやら、起動時に読み込んだクラスをリムーブしてるみたいですね。
      これ自体を読んだのであれば、全てが消えてしまう感じでこわいので、ここで使われているremove_constantメソッドだけを使って、該当のクラスを読み込み直しました。

      ActiveSupport::Dependencies.remove_constant "Modelのクラス名"
      load "Modelクラスへのパス"

      すると、晴れてアクセスする度に表示する時間が変わりました。
      #:nodoc:となっていますのでこのメソッドに解説がないのですが、このメソッドは以下のとおり。

      def remove_constant(const)
        return false unless qualified_const_defined? const
       
        const = $1 if /\A::(.*)\Z/ =~ const.to_s
        names = const.to_s.split('::')
        if names.size == 1 # It's under Object
          parent = Object
        else
          parent = (names[0..-2] * '::').constantize
        end
       
        log "removing constant #{const}"
        parent.instance_eval { remove_const names.last }
        return true
      end

      引数で渡したクラス名をチェックしたのち、
      remove_constという記述があり、クラスの定数を削除しているようです。

      一応、他のページ表示や処理にも問題ないようです。

      最適解か

      バリデーションのメッセージを動的に変えたい、という動機からここまでの調査に至りましたが、もっと簡単な方法があるのかもしれません。
      そもそも、どうしてもと言うならcontroller側でエラーメッセージを定義してもいいでしょうし。

      いかんともしがたい理由でmodelをアクセスの度にloadしたい方はご参考に~。

        はてなブックマーク - TwitterAPIの導入について
        このエントリーをはてなブックマークに追加

         まあ、有りますよね、二度目。

         Fusic2年目仁井です。よろしくお願いいたします。

         今回の記事は何にするか悩みました。iPadでゲーム作る記事にするとかダイエットの成功の記事にするとか色々考えたのですが、前回がTwitterでしたので今回も素直にTwitterで行きたいと思います。

         なんだかReturnキーが潰れてきた気がしますがそれは気にせずに。ええ。

        Twitter API

         ツイッターが市民権を得て随分と経ち、それに合わせて様々なツールやアプリケーションが開発されているかと思います。
         そんな開発に必須とも言えるのが、このTwitterAPIなんだよ、ジェシー! そうなのね、マイク!
         そうなんです。
         利用しているものとして想像しやすいのは、Botやクライアントあたりでしょう。
         リプライ、リツイート、フォロー、等々。ツイッターの代表的な機能をこれを使うことで自由に利用できます。
         それではその導入方法について、簡単に説明させていただきます。

        準備編:1

         それでは、TwitterAPIを使う準備を。
         まずクライアント製作者のアカウントでログインした状態でこのページにアクセスしてください。
         作成したクライアントは、この時ログインしているユーザとひもづけられます。
         ここで、アプリケーションの登録を行います。

         まず「新しいアプリケーションを登録する」をクリック。
         必要情報を入力しますが、注意すべきは2点。
        ・「アプリケーションの種類」は「クライアント」
        ・「標準のアクセスタイプ」は「Read&Write」
         をそれぞれ選択してください。間違えてもあとで修正できますので問題ないです。
         特に「標準のアクセスタイプ」を「Read-Only」にすると投稿などができなくなるので注意です。
        Image

        準備編:2

         つづいて、アプリケーション側の準備を。
         今回の環境はPHP5.2です。PHPは5以上で「curl」が使える環境であれば問題ありません。
         PHP環境が準備できたら今度はここの「Download」からファイルをダウンロードしてください。
         ファイルを解凍して、twitteroauthの中の「OAuth.php」と「twitteroauth.php」を取り出してください。この2つのファイルを使用します。

        実装編

         それでは実装について。
         以下のコードを参照してください。

        require_once("./twitteroauth.php");
         
        $to = new TwitterOAuth(CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET);
         
        $sendMessage = "さあ、呟いてみませんか";
        $req = $to->OAuthRequest('https://twitter.com/statuses/update.xml', 'POST', array('status' => $sendMessage));
         
        header("Content-Type: application/xml");
        echo $req;

        このスクリプトを実行すると、自分のアカウントに「さあ、呟いてみませんか」というツイートが投稿されます。
        なんとなく、botの姿が見えてきた感がありますね。
        ここで肝になるのが、オブジェクトの生成の時に与えている引数です。

        CONSUMER_KEY, CONSUMER_SECRET, ACCESS_TOKEN, ACCESS_TOKEN_SECRET

        この4つの値は全て、先ほどアプリケーション登録を行ったページから参照することができます。
        もう一度先程のページにアクセスします。
        すると「現在登録されているアプリケーション一覧」の中に、先ほど登録したアプリケーションが並んでいることと思います。
        それをクリックすると、下の方に「Consumer key」と「Consumer secret」の値が。
        さらにページ内の「My Access Token」のリンクの先には「Access Token」「Access Token Secret」があります。
        この値をそれぞれ引数にあたえるだけです。

        これで、Twitter APIを利用したツイートの投稿が可能になりました。

        注意点

         便利なTwitterAPIですが、注意点もございます。
         各機能には、それぞれ制限が設けられています。
         例えば、1時間の間に呟ける回数や、フォロー出来る人数など、それぞれに回数制限が存在しています。
         オーバーしたりするとアカウントを凍結されてしまうおそれも有りますので、使用の際は十分に注意をしてください。
         botを作って、誰彼構わず反応するようにしていると、あっという間に制限数を超えてしまうかも。
         ちなみに前回紹介した検索機能は
        ・1時間に150回
        ・1日に1000回
         の使用制限がIPベースで設けられています。

        最後に

         APIを使用することで、タイムラインの取得も可能です。
         そのなかから、自分に対するリプライや、リツイート等も取得可能です。パラメータの与え方次第で必要な情報をうまいこと集めましょう。
         ここまで出来るようになると、Twitterクライアントの作成も不可能ではありません。いえ、私はやりませんが。
         こちらのドキュメントの日本語訳が分かりやすく、大変お世話になりました。
         いい加減Returnキーの潰れ具合が腹に据えかねて来たので、このへんで筆を置く事と致します。
         それでは。クリスマス爆発しろ。仁井でした。