IEのFlashPlayerはページを閉じてもrtmpセッションが切れないことがある

2009.03.17 / actionscript

タイトルの現象は確認したものの、発生条件は確かなことはまだ言えないかも。。とりあえず現象報告とその対応策について。

問題

FlashPlayer上でRTMPセッションを張っているときにおいて、通常はページ遷移時においてFlashPlayerのインスタンスも同時に破棄される(はずな)ので、RTMPセッションもcloseされます。ところがIE7 + FlashPlayer9または10において、ページ遷移ではFlashPlayerが破棄されないケースがあるようです。なので、RTMPサーバ(たとえばWowza Media Server)にセッションを張っている場合、FlashPlayerが破棄されないことから、セッションが張りっぱなしになって、サーバ側でdisconnectをハンドリングできないことになります。

では、どうすれば破棄されるかというと、「IEを完全に終了」させて初めてFlashPlayerが破棄され、セッションが切れるようです。(ブラウザを閉じたときに初めてdisconnectイベントが上がってくることを確認しました。)Player側は、connectしてコンテンツを再生することについてはよく考えがちですが、ページのunload時においてはそもそも何も表示されていない状態なので、正常に接続がcloseされてあるかはちゃんと見ていないケースが多かったのが問題でした。

さて、このdisconnectイベントが上がってこない、というのは結構困るケースもあります。たとえばconnectイベントとdisconnectイベントが起きた時間を保存しておくと、サーバの任意の時刻におけるユーザの最大同時接続数を計測できますが、その計測はdisconnectイベントが上がってこないと難しくなります。(これはWebレイヤーだけだとちょっと難しいですね。)なので、この問題について、何らかの対策が必要となります。

対応策

対応策としては、こんな手順で対応できました。割と素直な方法。

  1. HTMLページのbeforeunloadイベントをフック
  2. RTMPセッションを張っているswfに対してExternalInterface経由でメソッド呼び出し
  3. swfは呼び出されたメソッドにおいて、NetConnectionをclose

と、こんなかんじです。beforeunloadのフックについてはこんなかんじでいいですね。swfはobject要素のid属性、およびembed要素のname属性が"externalpl"で指定されてあるものとします。ExternalInterfaceで呼び出すメソッド名がcloseAllになります。

      window.onbeforeunload = function(event){
          var swf = (document.all? window['externalpl'] : document['externalpl']) || null;
          if(swf && swf.closeAll) { swf.closeAll();} 
          document.getElementById('swf-container').innerHTML="";
      };
  
  

ちなみに、メソッドを呼び出した後はswfをロードしているHTML要素のswf-containerを空にして、FlashPlayerをunloadさせています。実際はこれまでに書いたとおり、IEにおいてはunloadされないのですが、それ以外の環境ではこの時点でunloadされるのでswfのファイルサイズが大きい場合、ページ遷移を行いやすくする利点があります。(最近知りました)

コールされるswf側はExternalInterface.addCallbackで実行されるメソッドを登録しておけばOKですね。

  import flash.external.ExternalInterface;
  ...
  ExternalInterface.addCallbak("closeAll", _closeAll);
  ...
  function _closeAll():void{
        nc.close();
        nc = null;
  } 
  

これでIEのFlashPlayerを利用している場合でも、RTMPサーバ側でdisconnectイベントをフックすることが可能になります。なかなか面倒なバッドノウハウでした。。

ちなみに

この現象を確認したのはWowza Media Server1.6.0です。FMSだとちゃんとイベントが上がってきたりするのかどうか、なんかも気になるところです。